From 5bc3b23c234bb8f2798512fb4f9d51052be58b60 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 5 Jun 2018 17:10:28 +0200 Subject: [PATCH] Make router properties update when re-rendering (#4541) * Make router properties update when re-rendering * Remove documentation about methods that have been deprecated since v2/v3 * Update next export documentation --- lib/router/index.js | 15 ++++++++++++-- readme.md | 50 +++++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/lib/router/index.js b/lib/router/index.js index 1e4be58b..5507e8d6 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -14,11 +14,12 @@ const SingletonRouter = { } // Create public properties and methods of the router in the SingletonRouter -const propertyFields = ['components', 'pathname', 'route', 'query', 'asPath'] +const urlPropertyFields = ['pathname', 'route', 'query', 'asPath'] +const propertyFields = ['components'] const routerEvents = ['routeChangeStart', 'beforeHistoryChange', 'routeChangeComplete', 'routeChangeError', 'hashChangeStart', 'hashChangeComplete'] const coreMethodFields = ['push', 'replace', 'reload', 'back', 'prefetch', 'beforePopState'] -propertyFields.forEach((field) => { +propertyFields.concat(urlPropertyFields).forEach((field) => { // Here we need to use Object.defineProperty because, we need to return // the property assigned to the actual router // The value might get changed as we change routes and this is the @@ -122,9 +123,19 @@ export function _rewriteUrlForNextExport (url) { return newPath } +// This function is used to create the `withRouter` router instance export function makePublicRouterInstance (router) { const instance = {} + for (const property of urlPropertyFields) { + if (typeof router[property] === 'object') { + instance[property] = {...router[property]} // makes sure query is not stateful + continue + } + + instance[property] = router[property] + } + propertyFields.forEach((field) => { // Here we need to use Object.defineProperty because, we need to return // the property assigned to the actual router diff --git a/readme.md b/readme.md index f0a02893..f975ac3f 100644 --- a/readme.md +++ b/readme.md @@ -367,15 +367,11 @@ Client-side routing behaves exactly like the browser: 2. If it defines `getInitialProps`, data is fetched. If an error occurs, `_error.js` is rendered 3. After 1 and 2 complete, `pushState` is performed and the new component is rendered -Each top-level component receives a `url` property with the following API: +**Deprecated, use [withRouter](https://github.com/zeit/next.js#using-a-higher-order-component) instead** - 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 - -The second `as` parameter for `push` and `replace` is an optional _decoration_ of the URL. Useful if you configured custom routes on the server. ##### With URL object @@ -1419,16 +1415,35 @@ Note: we recommend putting `.next`, or your [custom dist folder](https://github.

-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 dynamic urls, prefetching, preloading and dynamic imports. +`next export` is a way to run your Next.js app as a standalone static app without the need for a Node.js server. +The exported app supports almost every feature of Next.js, including dynamic urls, prefetching, preloading and dynamic imports. + +The way `next export` works is by pre-rendering all pages possible to HTML. It does so based on a mapping of `pathname` key to page object. This mapping is called the `exportPathMap`. + +The page object has 2 values: + +- `page` - `String` the page inside the `pages` directory to render +- `query` - `Object` the `query` object passed to `getInitialProps` when pre-rendering. Defaults to `{}` + ### 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: +Simply develop your app as you normally do with Next.js. Then run: + +``` +next build +next export +``` + +By default `next export` doesn't require any configuration. It will generate a default `exportPathMap` containing the routes to pages inside the `pages` directory. + +If your application has dynamic routes you can add a dynamic `exportPathMap` in `next.config.js`. +This function is asynchronous and gets the default `exportPathMap` as a parameter. ```js // next.config.js module.exports = { - exportPathMap: function(defaultPathMap) { + exportPathMap: async function (defaultPathMap) { return { '/': { page: '/' }, '/about': { page: '/about' }, @@ -1443,8 +1458,6 @@ module.exports = { > Note that if the path ends with a directory, it will be exported as `/dir-name/index.html`, but if it ends with an extension, it will be exported as the specified filename, e.g. `/readme.md` above. If you use a file extension other than `.html`, you may need to set the `Content-Type` header to `text/html` when serving this content. -In that, you specify what are the pages you need to export as static HTML. - Then simply run these commands: ```sh @@ -1457,7 +1470,8 @@ For that you may need to add a NPM script to `package.json` like this: ```json { "scripts": { - "build": "next build && next export" + "build": "next build", + "export": "npm run build && next export" } } ``` @@ -1465,16 +1479,16 @@ For that you may need to add a NPM script to `package.json` like this: And run it at once with: ```sh -npm run build +npm run export ``` -Then you've a static version of your app in the “out" directory. +Then you have 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. Note that there is an additional step for deploying to GitHub Pages, [documented here](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages). +Now you can deploy the `out` directory to any static hosting service. Note that there is an additional step for deploying to GitHub Pages, [documented here](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages). -For an example, simply visit the “out” directory and run following command to deploy your app to [ZEIT now](https://zeit.co/now). +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 @@ -1482,11 +1496,11 @@ 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. +With `next export`, we build a HTML version of your app. At export time we will run `getInitialProps` 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. +The `req` and `res` fields of the `context` object passed to `getInitialProps` are not available as there is no server running. -> 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`. +> You won't be able to render HTML dynamically when static exporting, as we pre-build the HTML files. If you want to do dynamic rendering use `next start` or the custom server API ## Multi Zones