Skip to content

Commit

Permalink
exportPathMap dynamic routes params fix (vercel#7846)
Browse files Browse the repository at this point in the history
* Fix dynamic page export fixes vercel#7829

* Adding handling of unmatched path

* Remove logs

* Fix newline

* Tests

* Fix promise

* Fix amp tests

* Revert test

* Adjust error document

* Remove old argument

* Simplify export test

* Ensure page !== path for this check
  • Loading branch information
huv1k authored and Timer committed Jul 10, 2019
1 parent 41cb3b3 commit 2450c85
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 4 deletions.
26 changes: 26 additions & 0 deletions errors/export-path-mismatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The provided export path doesn't match the page.

#### Why This Error Occurred

An `exportPathMap` path was improperly matched to a dynamically routed page.
This would result in the page missing its URL parameters.

#### Possible Ways to Fix It

Change your `exportPathMap` function in `next.config.js` to have a path that matches the dynamically routed page.

```js
module.exports = {
exportPathMap: function() {
return {
'/': { page: '/' },
// '/blog/nextjs': { page: '/blog/[post]/comment/[id]' }, // wrong
'/blog/nextjs/comment/1': { page: '/blog/[post]/comment/[id]' }, // correct
}
},
}
```

### Useful Links

- [exportPathMap](https://github.com/zeit/next.js#usage) documentation
21 changes: 20 additions & 1 deletion packages/next/export/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { Sema } from 'async-sema'
import AmpHtmlValidator from 'amphtml-validator'
import { loadComponents } from 'next-server/dist/server/load-components'
import { inlineGipIdentifier } from '../build/babel/plugins/next-page-config'
import { isDynamicRoute } from 'next-server/dist/lib/router/utils/is-dynamic'
import { getRouteMatcher } from 'next-server/dist/lib/router/utils/route-matcher'
import { getRouteRegex } from 'next-server/dist/lib/router/utils/route-regex'

const envConfig = require('next-server/config')
const mkdirp = promisify(mkdirpModule)
Expand Down Expand Up @@ -37,7 +40,23 @@ process.on(
const work = async path => {
await sema.acquire()
const ampPath = `${path === '/' ? '/index' : path}.amp`
const { page, query = {} } = exportPathMap[path]
const { page } = exportPathMap[path]
let { query = {} } = exportPathMap[path]

// Check if the page is a specified dynamic route
if (isDynamicRoute(page) && page !== path) {
const params = getRouteMatcher(getRouteRegex(page))(path)
if (params) {
query = {
...query,
...params
}
} else {
throw new Error(
`The provided export path '${path}' doesn't match the '${page}' page.\nRead more: https://err.sh/zeit/next.js/export-path-mismatch`
)
}
}

const headerMocks = {
headers: {},
Expand Down
3 changes: 2 additions & 1 deletion test/integration/export/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ module.exports = phase => {
page: '/dynamic',
query: { text: 'this file has an extension' }
},
'/query': { page: '/query', query: { a: 'blue' } }
'/query': { page: '/query', query: { a: 'blue' } },
'/blog/nextjs/comment/test': { page: '/blog/[post]/comment/[id]' }
}
} // end exportPathMap
}
Expand Down
18 changes: 18 additions & 0 deletions test/integration/export/pages/blog/[post]/comment/[id].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useRouter } from 'next/router'

const Page = () => {
const router = useRouter()
const { post, id } = router.query

return (
<>
<p>
{`Blog post ${post} comment ${id || '(all)'}`}
</p>
</>
)
}

Page.getInitialProps = () => ({})

export default Page
27 changes: 27 additions & 0 deletions test/integration/export/test/dynamic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-env jest */
import { join } from 'path'
import { File, runNextCommand } from 'next-test-utils'

export default function (context) {
describe('Dynamic routes export', () => {
const nextConfig = new File(join(context.appDir, 'next.config.js'))
beforeEach(() => {
nextConfig.replace('/blog/nextjs/comment/test', '/bad/path')
})
afterEach(() => {
nextConfig.restore()
})

it('Should throw error not matched route', async () => {
const outdir = join(context.appDir, 'outDynamic')
const { stderr } = await runNextCommand(
['export', context.appDir, '--outdir', outdir],
{ stderr: true }
).catch(err => err)

expect(stderr).toContain(
'https://err.sh/zeit/next.js/export-path-mismatch'
)
})
})
}
3 changes: 3 additions & 0 deletions test/integration/export/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import browser from './browser'
import dev from './dev'
import { promisify } from 'util'
import fs from 'fs'
import dynamic from './dynamic'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5

Expand All @@ -26,6 +27,7 @@ const mkdir = promisify(fs.mkdir)
const access = promisify(fs.access)
const appDir = join(__dirname, '../')
const context = {}
context.appDir = appDir
const devContext = {}
const nextConfig = new File(join(appDir, 'next.config.js'))

Expand Down Expand Up @@ -93,4 +95,5 @@ describe('Static Export', () => {
ssr(context)
browser(context)
dev(devContext)
dynamic(context)
})
9 changes: 8 additions & 1 deletion test/integration/export/test/ssr.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,17 @@ export default function (context) {
const html = await renderViaHTTP(context.port, '/about')
const html2 = await renderViaHTTP(context.port, '/query')
const data = await renderViaHTTP(context.port, '/about/data.txt')

expect(html).toMatch(/This is the About page foobar/)
expect(html2).toMatch(/{"a":"blue"}/)
expect(data).toBe('data')
})

it('Should render dynamic files with query', async () => {
const html = await renderViaHTTP(
context.port,
'/blog/nextjs/comment/test'
)
expect(html).toMatch(/Blog post nextjs comment test/)
})
})
}
4 changes: 3 additions & 1 deletion test/lib/next-test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ export function buildTS (args = [], cwd, env = {}) {
instance.stderr.on('data', handleData)

instance.on('exit', code => {
if (code) { return reject(new Error('exited with code: ' + code + '\n' + output)) }
if (code) {
return reject(new Error('exited with code: ' + code + '\n' + output))
}
resolve()
})
})
Expand Down

0 comments on commit 2450c85

Please sign in to comment.