diff --git a/.gitignore b/.gitignore index 1f02e940..8f980adb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,12 @@ dist node_modules # logs -npm-debug.log +*.log # coverage .nyc_output coverage +# test output +test/**/out .DS_Store diff --git a/bin/next b/bin/next index 79f635b7..234b3d5b 100755 --- a/bin/next +++ b/bin/next @@ -22,6 +22,7 @@ const commands = new Set([ 'init', 'build', 'start', + 'export', defaultCommand ]) diff --git a/bin/next-export b/bin/next-export new file mode 100644 index 00000000..37508242 --- /dev/null +++ b/bin/next-export @@ -0,0 +1,67 @@ +#!/usr/bin/env node +import { resolve, join } from 'path' +import { existsSync } from 'fs' +import parseArgs from 'minimist' +import exportApp from '../server/export' +import { printAndExit } from '../lib/utils' + +process.env.NODE_ENV = process.env.NODE_ENV || 'production' + +const argv = parseArgs(process.argv.slice(2), { + alias: { + h: 'help', + s: 'silent', + o: 'outdir' + }, + boolean: ['h'], + default: { + s: false, + o: null + } +}) + +if (argv.help) { + console.log(` + Description + Exports the application for production deployment + + Usage + $ next export [options]
It's possible to use any existing CSS-in-JS solution. The simplest one is inline styles: @@ -239,6 +247,7 @@ export default Page - `pathname` - path section of URL - `query` - query string section of URL parsed as an object +- `asPath` - the actual url path - `req` - HTTP request object (server only) - `res` - HTTP response object (server only) - `jsonPageRes` - [Fetch Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object (client only) @@ -284,6 +293,7 @@ Each top-level component receives a `url` property with the following API: - `pathname` - `String` of the current path excluding the query string - `query` - `Object` with the parsed query string. Defaults to `{}` +- `asPath` - `String` of the actual path (including the query) shows in the browser - `push(url, as=url)` - performs a `pushState` call with the given url - `replace(url, as=url)` - performs a `replaceState` call with the given url @@ -703,6 +713,8 @@ The `ctx` object is equivalent to the one received in all [`getInitialProps`](#f - `renderPage` (`Function`) a callback that executes the actual React rendering logic (synchronously). It's useful to decorate this function in order to support server-rendering wrappers like Aphrodite's [`renderStatic`](https://github.com/Khan/aphrodite#server-side-rendering) +__Note: React-components outside of `` will not be initialised by the browser. If you need shared components in all your pages (like a menu or a toolbar), do _not_ add application logic here, but take a look at [this example](https://github.com/zeit/next.js/tree/master/examples/layout-component).__ + ### Custom error handling 404 or 500 errors are handled both client and server side by a default component `error.js`. If you wish to override it, define a `_error.js`: @@ -762,9 +774,15 @@ In order to extend our usage of `webpack`, you can define a function that extend module.exports = { webpack: (config, { dev }) => { - // Perform customizations to config - - // Important: return the modified config + // Perform customizations to webpack config + + // Important: return the modified config + return config + }, + webpackDevMiddleware: (config) => { + // Perform customizations to webpack dev middleware config + + // Important: return the modified config return config } } @@ -841,6 +859,79 @@ Next.js can be deployed to other hosting solutions too. Please have a look at th Note: we recommend putting `.next`, or your custom dist folder (Please have a look at ['Custom Config'](You can set a custom folder in config https://github.com/zeit/next.js#custom-configuration.)), in `.npmignore` or `.gitignore`. Otherwise, use `files` or `now.files` to opt-into a whitelist of files you want to deploy (and obviously exclude `.next` or your custom dist folder) +## Static HTML export + +This is a way to run your Next.js app as a standalone static app without any Node.js server. The export app supports almost every feature of Next.js including dyanmic urls, prefetching, preloading and dynamic imports. + +### Usage + +Simply develop your app as you normally do with Next.js. Then create a custom Next.js [config](https://github.com/zeit/next.js#custom-configuration) as shown below: + +```js +// next.config.js +module.exports = { + exportPathMap: function () { + return { + "/": { page: "/" }, + "/about": { page: "/about" }, + "/p/hello-nextjs": { page: "/post", query: { title: "hello-nextjs" } }, + "/p/learn-nextjs": { page: "/post", query: { title: "learn-nextjs" } }, + "/p/deploy-nextjs": { page: "/post", query: { title: "deploy-nextjs" } } + } + }, +} +``` + +In that, you specify what are the pages you need to export as static HTML. + +Then simply run these commands: + +```sh +next build +next export +``` + +For that you may need to add a NPM script to `package.json` like this: + +```json +{ + "scripts": { + "build": "next build && next export" + } +} +``` + +And run it at once with: + +```sh +npm run build +``` + +Then you've a static version of your app in the “out" directory. + +> You can also customize the output directory. For that run `next export -h` for the help. + +Now you can deploy that directory to any static hosting service. + +For an example, simply visit the “out” directory and run following command to deploy your app to [ZEIT now](https://zeit.co/now). + +```sh +now +``` + +### Limitation + +With next export, we build HTML version of your app when you run the command `next export`. In that time, we'll run the `getInitialProps` functions of your pages. + +So, you could only use `pathname`, `query` and `asPath` fields of the `context` object passed to `getInitialProps`. You can't use `req` or `res` fields. + +> Basically, you won't be able to render HTML content dynamically as we pre-build HTML files. If you need that, you need run your app with `next start`. + + +## Recipes + +- [Setting up 301 redirects](https://www.raygesualdo.com/posts/301-redirects-with-nextjs/) + ## FAQ