Skip to content

Commit

Permalink
Make router properties update when re-rendering (vercel#4541)
Browse files Browse the repository at this point in the history
* Make router properties update when re-rendering

* Remove documentation about methods that have been deprecated since v2/v3

* Update next export documentation
  • Loading branch information
timneutkens authored and lependu committed Jun 19, 2018
1 parent a16a055 commit 7860111
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
15 changes: 13 additions & 2 deletions lib/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
50 changes: 32 additions & 18 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -1419,16 +1415,35 @@ Note: we recommend putting `.next`, or your [custom dist folder](https://github.
<ul><li><a href="./examples/with-static-export">Static export</a></li></ul>
</details></p>

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' },
Expand All @@ -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
Expand All @@ -1457,36 +1470,37 @@ 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"
}
}
```

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
```

### 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

Expand Down

0 comments on commit 7860111

Please sign in to comment.