From cedd6faba6f4f183d51cac612bc274e5c346e09b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 25 Feb 2020 13:20:49 +0100 Subject: [PATCH 01/12] Create config.yml --- .github/ISSUE_TEMPLATE/config.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000000..a26c9187784a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: GitHub Discussions + url: https://github.com/zeit/next.js/discussions + about: Please ask and answer questions here. From 06afa0a09c6430f0120100ce2e719720f7090662 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 25 Feb 2020 13:21:42 +0100 Subject: [PATCH 02/12] Delete 8.Question_about_next.md --- .github/ISSUE_TEMPLATE/8.Question_about_next.md | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/8.Question_about_next.md diff --git a/.github/ISSUE_TEMPLATE/8.Question_about_next.md b/.github/ISSUE_TEMPLATE/8.Question_about_next.md deleted file mode 100644 index fdfd0c1e9ee1..000000000000 --- a/.github/ISSUE_TEMPLATE/8.Question_about_next.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Question about Next.js -about: If you have a question related to Next.js or the examples. Reach out to the community on GitHub discussions ---- - -# Question about Next.js - -GitHub Issues are reserved for Bug reports and Feature requests. - -The best place to get your question answered is to post it on GitHub Discussions: https://github.com/zeit/next.js/discussions/new. From 297c23d9cfd38542f2966954de3e8626e6414216 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 25 Feb 2020 13:22:28 +0100 Subject: [PATCH 03/12] Delete 3.Example_Bug_report.md --- .../ISSUE_TEMPLATE/3.Example_Bug_report.md | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/3.Example_Bug_report.md diff --git a/.github/ISSUE_TEMPLATE/3.Example_Bug_report.md b/.github/ISSUE_TEMPLATE/3.Example_Bug_report.md deleted file mode 100644 index a1640aee8e59..000000000000 --- a/.github/ISSUE_TEMPLATE/3.Example_Bug_report.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -name: Bug report for examples -about: Create a bug report for one of the Next.js examples ---- - -# Examples bug report - -## Example name - -Provide the example name - -## Describe the bug - -A clear and concise description of what the bug is. - -## To Reproduce - -Steps to reproduce the behavior, please provide code snippets or a repository: - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -## Expected behavior - -A clear and concise description of what you expected to happen. - -## Screenshots - -If applicable, add screenshots to help explain your problem. - -## System information - -- OS: [e.g. macOS, Windows] -- Browser (if applies) [e.g. chrome, safari] -- Version of Next.js: [e.g. 6.0.2] - -## Additional context - -Add any other context about the problem here. From fc9f18d78410a09fc1cd90326068106e918310d7 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 25 Feb 2020 13:22:48 +0100 Subject: [PATCH 04/12] Update 1.Bug_report.md --- .github/ISSUE_TEMPLATE/1.Bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/1.Bug_report.md b/.github/ISSUE_TEMPLATE/1.Bug_report.md index 6c10e9edc66b..ba86015e91e3 100644 --- a/.github/ISSUE_TEMPLATE/1.Bug_report.md +++ b/.github/ISSUE_TEMPLATE/1.Bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Create a bug report for the Next.js core +about: Create a bug report for the Next.js core / examples --- # Bug report From 3b28702983bc7212e40aa454c0e1ae53b41fe763 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 25 Feb 2020 13:24:06 +0100 Subject: [PATCH 05/12] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index a26c9187784a..3ea766fd6d3a 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - - name: GitHub Discussions + - name: Ask a question url: https://github.com/zeit/next.js/discussions - about: Please ask and answer questions here. + about: Ask questions and discuss with other community members From a81913f1ba019c767da0d876a0b18f2922bd9d5e Mon Sep 17 00:00:00 2001 From: Henrik Wenz Date: Tue, 25 Feb 2020 22:16:34 +0100 Subject: [PATCH 06/12] Fix apollo example (#10696) --- examples/with-apollo/lib/apollo.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/with-apollo/lib/apollo.js b/examples/with-apollo/lib/apollo.js index e13a68f240ab..17a40a6d309c 100644 --- a/examples/with-apollo/lib/apollo.js +++ b/examples/with-apollo/lib/apollo.js @@ -1,5 +1,6 @@ import React from 'react' import App from 'next/app' +import Head from 'next/head' import { ApolloProvider } from '@apollo/react-hooks' import createApolloClient from '../apolloClient' @@ -153,6 +154,10 @@ export const withApollo = ({ ssr = false } = {}) => PageComponent => { // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error console.error('Error while running `getDataFromTree`', error) } + + // getDataFromTree does not call componentWillUnmount + // head side effect therefore need to be cleared manually + Head.rewind() } } From 513a7d5b5c44a1a288b68a9c06616e3356808098 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 26 Feb 2020 13:56:13 +0100 Subject: [PATCH 07/12] Update head-manager to compress better (#10687) * Update head-manager to compress better * Decrease size limit test --- packages/next/client/head-manager.js | 154 ++++++++---------- packages/next/client/index.js | 6 +- .../integration/size-limit/test/index.test.js | 2 +- 3 files changed, 74 insertions(+), 88 deletions(-) diff --git a/packages/next/client/head-manager.js b/packages/next/client/head-manager.js index 5eec36503c0c..08b5c45a527a 100644 --- a/packages/next/client/head-manager.js +++ b/packages/next/client/head-manager.js @@ -5,90 +5,6 @@ const DOMAttributeNames = { httpEquiv: 'http-equiv', } -export default class HeadManager { - constructor() { - this.updatePromise = null - } - - updateHead = head => { - const promise = (this.updatePromise = Promise.resolve().then(() => { - if (promise !== this.updatePromise) return - - this.updatePromise = null - this.doUpdateHead(head) - })) - } - - doUpdateHead(head) { - const tags = {} - head.forEach(h => { - const components = tags[h.type] || [] - components.push(h) - tags[h.type] = components - }) - - this.updateTitle(tags.title ? tags.title[0] : null) - - const types = ['meta', 'base', 'link', 'style', 'script'] - types.forEach(type => { - this.updateElements(type, tags[type] || []) - }) - } - - updateTitle(component) { - let title = '' - if (component) { - const { children } = component.props - title = typeof children === 'string' ? children : children.join('') - } - if (title !== document.title) document.title = title - } - - updateElements(type, components) { - const headEl = document.getElementsByTagName('head')[0] - const headCountEl = headEl.querySelector('meta[name=next-head-count]') - if (process.env.NODE_ENV !== 'production') { - if (!headCountEl) { - console.error( - 'Warning: next-head-count is missing. https://err.sh/next.js/next-head-count-missing' - ) - return - } - } - - const headCount = Number(headCountEl.content) - const oldTags = [] - - for ( - let i = 0, j = headCountEl.previousElementSibling; - i < headCount; - i++, j = j.previousElementSibling - ) { - if (j.tagName.toLowerCase() === type) { - oldTags.push(j) - } - } - const newTags = components.map(reactElementToDOM).filter(newTag => { - for (let k = 0, len = oldTags.length; k < len; k++) { - const oldTag = oldTags[k] - if (oldTag.isEqualNode(newTag)) { - oldTags.splice(k, 1) - return false - } - } - return true - }) - - oldTags.forEach(t => t.parentNode.removeChild(t)) - newTags.forEach(t => headEl.insertBefore(t, headCountEl)) - headCountEl.content = ( - headCount - - oldTags.length + - newTags.length - ).toString() - } -} - function reactElementToDOM({ type, props }) { const el = document.createElement(type) for (const p in props) { @@ -110,3 +26,73 @@ function reactElementToDOM({ type, props }) { } return el } + +function updateElements(type, components) { + const headEl = document.getElementsByTagName('head')[0] + const headCountEl = headEl.querySelector('meta[name=next-head-count]') + if (process.env.NODE_ENV !== 'production') { + if (!headCountEl) { + console.error( + 'Warning: next-head-count is missing. https://err.sh/next.js/next-head-count-missing' + ) + return + } + } + + const headCount = Number(headCountEl.content) + const oldTags = [] + + for ( + let i = 0, j = headCountEl.previousElementSibling; + i < headCount; + i++, j = j.previousElementSibling + ) { + if (j.tagName.toLowerCase() === type) { + oldTags.push(j) + } + } + const newTags = components.map(reactElementToDOM).filter(newTag => { + for (let k = 0, len = oldTags.length; k < len; k++) { + const oldTag = oldTags[k] + if (oldTag.isEqualNode(newTag)) { + oldTags.splice(k, 1) + return false + } + } + return true + }) + + oldTags.forEach(t => t.parentNode.removeChild(t)) + newTags.forEach(t => headEl.insertBefore(t, headCountEl)) + headCountEl.content = (headCount - oldTags.length + newTags.length).toString() +} + +export default function initHeadManager() { + let updatePromise = null + + return head => { + const promise = (updatePromise = Promise.resolve().then(() => { + if (promise !== updatePromise) return + + updatePromise = null + const tags = {} + + head.forEach(h => { + const components = tags[h.type] || [] + components.push(h) + tags[h.type] = components + }) + + const titleComponent = tags.title ? tags.title[0] : null + let title = '' + if (titleComponent) { + const { children } = titleComponent.props + title = typeof children === 'string' ? children : children.join('') + } + if (title !== document.title) document.title = title + ;['meta', 'base', 'link', 'style', 'script'].forEach(type => { + updateElements(type, tags[type] || []) + }) + })) + } +} diff --git a/packages/next/client/index.js b/packages/next/client/index.js index 8cd2473aa15c..124b8ab35dc1 100644 --- a/packages/next/client/index.js +++ b/packages/next/client/index.js @@ -1,7 +1,7 @@ /* global location */ import React from 'react' import ReactDOM from 'react-dom' -import HeadManager from './head-manager' +import initHeadManager from './head-manager' import { createRouter, makePublicRouterInstance } from 'next/router' import mitt from '../next-server/lib/mitt' import { loadGetInitialProps, getURL, ST } from '../next-server/lib/utils' @@ -57,7 +57,7 @@ if (window.__NEXT_P) { window.__NEXT_P = [] window.__NEXT_P.push = register -const headManager = new HeadManager() +const updateHead = initHeadManager() const appElement = document.getElementById('__next') let lastAppProps @@ -397,7 +397,7 @@ function AppContainer({ children }) { } > - + {children} diff --git a/test/integration/size-limit/test/index.test.js b/test/integration/size-limit/test/index.test.js index 0d36408825aa..1700dafa5efe 100644 --- a/test/integration/size-limit/test/index.test.js +++ b/test/integration/size-limit/test/index.test.js @@ -80,7 +80,7 @@ describe('Production response size', () => { ) // These numbers are without gzip compression! - const delta = responseSizesBytes - 238 * 1024 + const delta = responseSizesBytes - 237 * 1024 expect(delta).toBeLessThanOrEqual(1024) // don't increase size more than 1kb expect(delta).toBeGreaterThanOrEqual(-1024) // don't decrease size more than 1kb without updating target }) From c0f42837bf7ae1fc4d2bb2b15b84e7dfd8e2ad92 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 26 Feb 2020 15:00:26 +0100 Subject: [PATCH 08/12] Update README.md --- packages/next/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/README.md b/packages/next/README.md index eb677e47512d..1696181cd3d1 100644 --- a/packages/next/README.md +++ b/packages/next/README.md @@ -10,7 +10,7 @@ - +
extends React.Component< render() { const { router, Component, pageProps } = this.props as AppProps - const url = createUrl(router) - return + + return ( + + ) } } diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 1c932da181e2..68a7215ce68b 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -23,6 +23,7 @@ const nextConfig = join(appDir, 'next.config.js') let app let appPort let buildId +let stderr const expectedManifestRoutes = () => ({ '/something': { @@ -322,6 +323,31 @@ const runTests = (dev = false) => { }) if (dev) { + it('should not show warning from url prop being returned', async () => { + const urlPropPage = join(appDir, 'pages/url-prop.js') + await fs.writeFile( + urlPropPage, + ` + export async function unstable_getServerProps() { + return { + props: { + url: 'something' + } + } + } + + export default ({ url }) => url: {url} + ` + ) + + const html = await renderViaHTTP(appPort, '/url-prop') + await fs.remove(urlPropPage) + expect(stderr).not.toMatch( + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden on page \/url-prop/ + ) + expect(html).toMatch(/url:.*?something/) + }) + it('should show error for extra keys returned from getServerProps', async () => { const html = await renderViaHTTP(appPort, '/invalid-keys') expect(html).toContain( @@ -365,8 +391,13 @@ const runTests = (dev = false) => { describe('unstable_getServerProps', () => { describe('dev mode', () => { beforeAll(async () => { + stderr = '' appPort = await findPort() - app = await launchApp(appDir, appPort) + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg + }, + }) buildId = 'development' }) afterAll(() => killApp(app)) @@ -382,8 +413,13 @@ describe('unstable_getServerProps', () => { 'utf8' ) await nextBuild(appDir) + stderr = '' appPort = await findPort() - app = await nextStart(appDir, appPort) + app = await nextStart(appDir, appPort, { + onStderr(msg) { + stderr += msg + }, + }) buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') }) afterAll(() => killApp(app)) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index f5431a853cd4..309f06690be3 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -428,6 +428,31 @@ const runTests = (dev = false, looseMode = false) => { // ) // }) + it('should not show warning from url prop being returned', async () => { + const urlPropPage = join(appDir, 'pages/url-prop.js') + await fs.writeFile( + urlPropPage, + ` + export async function unstable_getStaticProps() { + return { + props: { + url: 'something' + } + } + } + + export default ({ url }) => url: {url} + ` + ) + + const html = await renderViaHTTP(appPort, '/url-prop') + await fs.remove(urlPropPage) + expect(stderr).not.toMatch( + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden on page \/url-prop/ + ) + expect(html).toMatch(/url:.*?something/) + }) + it('should always show fallback for page not in getStaticPaths', async () => { const html = await renderViaHTTP(appPort, '/blog/post-321') const $ = cheerio.load(html) From 6dea45bdc930dd2d9d602a1c3430b5b3422a42f1 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 26 Feb 2020 13:35:02 -0600 Subject: [PATCH 11/12] Add dataRoutes field to routes-manifest for SSG and serverProps routes (#10622) * Add dataRoutes field to routes-manifest for SSG and serverProps routes * Update routes-manifest test --- packages/next/build/index.ts | 15 +-- .../dynamic-routing/test/index.test.js | 31 ++++++ .../getserverprops/test/index.test.js | 98 ++++++++++--------- test/integration/prerender/test/index.test.js | 77 +++++++++++++++ 4 files changed, 169 insertions(+), 52 deletions(-) diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 841f5472178b..849dff8b950b 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -569,12 +569,13 @@ export default async function build(dir: string, conf = null): Promise { ) staticCheckWorkers.end() - if (serverPropsPages.size > 0) { + if (serverPropsPages.size > 0 || ssgPages.size > 0) { // We update the routes manifest after the build with the - // serverProps routes since we can't determine this until after build - routesManifest.serverPropsRoutes = {} - - for (const page of serverPropsPages) { + // data routes since we can't determine these until after build + routesManifest.dataRoutes = getSortedRoutes([ + ...serverPropsPages, + ...ssgPages, + ]).map(page => { const pagePath = normalizePagePath(page) const dataRoute = path.posix.join( '/_next/data', @@ -582,7 +583,7 @@ export default async function build(dir: string, conf = null): Promise { `${pagePath}.json` ) - routesManifest.serverPropsRoutes[page] = { + return { page, dataRouteRegex: isDynamicRoute(page) ? getRouteRegex(dataRoute.replace(/\.json$/, '')).re.source.replace( @@ -597,7 +598,7 @@ export default async function build(dir: string, conf = null): Promise { )}$` ).source, } - } + }) await fsWriteFile( routesManifestPath, diff --git a/test/integration/dynamic-routing/test/index.test.js b/test/integration/dynamic-routing/test/index.test.js index 77978c4e95cb..4c73f4430f55 100644 --- a/test/integration/dynamic-routing/test/index.test.js +++ b/test/integration/dynamic-routing/test/index.test.js @@ -15,6 +15,7 @@ import { normalizeRegEx, } from 'next-test-utils' import cheerio from 'cheerio' +import escapeRegex from 'escape-string-regexp' jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2 @@ -485,6 +486,10 @@ function runTests(dev) { route.regex = normalizeRegEx(route.regex) } + for (const route of manifest.dataRoutes) { + route.dataRouteRegex = normalizeRegEx(route.dataRouteRegex) + } + expect(manifest).toEqual({ version: 1, pages404: true, @@ -492,6 +497,32 @@ function runTests(dev) { headers: [], rewrites: [], redirects: [], + dataRoutes: [ + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/p1\\/p2\\/all\\-ssg\\/(.+?)\\.json$` + ), + page: '/p1/p2/all-ssg/[...rest]', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/p1\\/p2\\/nested\\-all\\-ssg\\/(.+?)\\.json$` + ), + page: '/p1/p2/nested-all-ssg/[...rest]', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/p1\\/p2\\/predefined\\-ssg\\/(.+?)\\.json$` + ), + page: '/p1/p2/predefined-ssg/[...rest]', + }, + ], dynamicRoutes: [ { page: '/blog/[name]/comment/[id]', diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 68a7215ce68b..84707e9eccf5 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -25,72 +25,72 @@ let appPort let buildId let stderr -const expectedManifestRoutes = () => ({ - '/something': { - page: '/something', +const expectedManifestRoutes = () => [ + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/something.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/index.json$` ), + page: '/', }, - '/blog/[post]': { - page: '/blog/[post]', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/blog\\/([^/]+?)\\.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/another.json$` ), + page: '/another', }, - '/': { - page: '/', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/index.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/blog.json$` ), + page: '/blog', }, - '/default-revalidate': { - page: '/default-revalidate', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/default-revalidate.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/blog\\/([^\\/]+?)\\.json$` ), + page: '/blog/[post]', }, - '/catchall/[...path]': { - page: '/catchall/[...path]', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/catchall\\/(.+?)\\.json$` + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/blog\\/([^\\/]+?)\\/([^\\/]+?)\\.json$` ), + page: '/blog/[post]/[comment]', }, - '/blog': { - page: '/blog', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/blog.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/catchall\\/(.+?)\\.json$` ), + page: '/catchall/[...path]', }, - '/blog/[post]/[comment]': { - page: '/blog/[post]/[comment]', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex( - buildId - )}\\/blog\\/([^/]+?)\\/([^/]+?)\\.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/default-revalidate.json$` ), + page: '/default-revalidate', }, - '/user/[user]/profile': { - page: '/user/[user]/profile', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex( - buildId - )}\\/user\\/([^/]+?)\\/profile\\.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/invalid-keys.json$` ), + page: '/invalid-keys', }, - '/another': { - page: '/another', + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/another.json$` + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/something.json$` ), + page: '/something', }, - '/invalid-keys': { + { dataRouteRegex: normalizeRegEx( - `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/invalid-keys.json$` + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/user\\/([^\\/]+?)\\/profile\\.json$` ), - page: '/invalid-keys', + page: '/user/[user]/profile', }, -}) +] const navigateTest = (dev = false) => { it('should navigate between pages successfully', async () => { @@ -209,7 +209,10 @@ const runTests = (dev = false) => { expect(JSON.parse(query)).toEqual({ path: ['first'] }) const data = JSON.parse( - await renderViaHTTP(appPort, `/_next/data/${buildId}/catchall/first.json`) + await renderViaHTTP( + appPort, + `/_next/data/${escapeRegex(buildId)}/catchall/first.json` + ) ) expect(data.pageProps.params).toEqual({ path: ['first'] }) @@ -217,7 +220,10 @@ const runTests = (dev = false) => { it('should return data correctly', async () => { const data = JSON.parse( - await renderViaHTTP(appPort, `/_next/data/${buildId}/something.json`) + await renderViaHTTP( + appPort, + `/_next/data/${escapeRegex(buildId)}/something.json` + ) ) expect(data.pageProps.world).toBe('world') }) @@ -226,7 +232,7 @@ const runTests = (dev = false) => { const data = JSON.parse( await renderViaHTTP( appPort, - `/_next/data/${buildId}/something.json?another=thing` + `/_next/data/${escapeRegex(buildId)}/something.json?another=thing` ) ) expect(data.pageProps.query.another).toBe('thing') @@ -234,7 +240,10 @@ const runTests = (dev = false) => { it('should return data correctly for dynamic page', async () => { const data = JSON.parse( - await renderViaHTTP(appPort, `/_next/data/${buildId}/blog/post-1.json`) + await renderViaHTTP( + appPort, + `/_next/data/${escapeRegex(buildId)}/blog/post-1.json` + ) ) expect(data.pageProps.post).toBe('post-1') }) @@ -367,15 +376,14 @@ const runTests = (dev = false) => { }) it('should output routes-manifest correctly', async () => { - const { serverPropsRoutes } = await fs.readJSON( + const { dataRoutes } = await fs.readJSON( join(appDir, '.next/routes-manifest.json') ) - for (const key of Object.keys(serverPropsRoutes)) { - const val = serverPropsRoutes[key].dataRouteRegex - serverPropsRoutes[key].dataRouteRegex = normalizeRegEx(val) + for (const route of dataRoutes) { + route.dataRouteRegex = normalizeRegEx(route.dataRouteRegex) } - expect(serverPropsRoutes).toEqual(expectedManifestRoutes()) + expect(dataRoutes).toEqual(expectedManifestRoutes()) }) it('should set no-cache, no-store, must-revalidate header', async () => { diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 309f06690be3..7d52eaed288e 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -589,6 +589,83 @@ const runTests = (dev = false, looseMode = false) => { }) } + it('outputs dataRoutes in routes-manifest correctly', async () => { + const { dataRoutes } = JSON.parse( + await fs.readFile(join(appDir, '.next/routes-manifest.json'), 'utf8') + ) + + for (const route of dataRoutes) { + route.dataRouteRegex = normalizeRegEx(route.dataRouteRegex) + } + + expect(dataRoutes).toEqual([ + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/index.json$` + ), + page: '/', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/another.json$` + ), + page: '/another', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/blog.json$` + ), + page: '/blog', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/blog\\/([^\\/]+?)\\.json$` + ), + page: '/blog/[post]', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/blog\\/([^\\/]+?)\\/([^\\/]+?)\\.json$` + ), + page: '/blog/[post]/[comment]', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/catchall\\/(.+?)\\.json$` + ), + page: '/catchall/[...slug]', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/default-revalidate.json$` + ), + page: '/default-revalidate', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/something.json$` + ), + page: '/something', + }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex( + buildId + )}\\/user\\/([^\\/]+?)\\/profile\\.json$` + ), + page: '/user/[user]/profile', + }, + ]) + }) + it('outputs a prerender-manifest correctly', async () => { const manifest = JSON.parse( await fs.readFile(join(appDir, '.next/prerender-manifest.json'), 'utf8') From b3ffdabbadbfa8f3ebde55df419ae19e27217ece Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 26 Feb 2020 13:49:08 -0600 Subject: [PATCH 12/12] v9.2.3-canary.13 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/next-bundle-analyzer/package.json | 2 +- packages/next-mdx/package.json | 2 +- packages/next-plugin-google-analytics/package.json | 2 +- packages/next-plugin-material-ui/package.json | 2 +- packages/next-plugin-sentry/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next/package.json | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lerna.json b/lerna.json index 16f7b566a72b..d7ce38857e23 100644 --- a/lerna.json +++ b/lerna.json @@ -12,5 +12,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "9.2.3-canary.12" + "version": "9.2.3-canary.13" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 964c2db771de..6036cbedc0d7 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "keywords": [ "react", "next", diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 1fbd0f861d5d..9dc52445a1f5 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index 7e738971e6e1..63b50800e02c 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-google-analytics/package.json b/packages/next-plugin-google-analytics/package.json index be4a9963fb26..27c703f307cb 100644 --- a/packages/next-plugin-google-analytics/package.json +++ b/packages/next-plugin-google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-google-analytics", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "nextjs": { "name": "Google Analytics", "required-env": [ diff --git a/packages/next-plugin-material-ui/package.json b/packages/next-plugin-material-ui/package.json index e6c68f5361de..64968e3e1954 100644 --- a/packages/next-plugin-material-ui/package.json +++ b/packages/next-plugin-material-ui/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-material-ui", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "nextjs": { "name": "Material UI", "required-env": [] diff --git a/packages/next-plugin-sentry/package.json b/packages/next-plugin-sentry/package.json index 8856bcab3352..4f01cec1aede 100644 --- a/packages/next-plugin-sentry/package.json +++ b/packages/next-plugin-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-sentry", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "nextjs": { "name": "Sentry", "required-env": [ diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index 84df2a082b10..5c15bfa50511 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next/package.json b/packages/next/package.json index 3f8906b4f757..2ddb5038971f 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "9.2.3-canary.12", + "version": "9.2.3-canary.13", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -73,7 +73,7 @@ "@babel/preset-typescript": "7.7.2", "@babel/runtime": "7.7.2", "@babel/types": "7.7.4", - "@next/polyfill-nomodule": "9.2.3-canary.12", + "@next/polyfill-nomodule": "9.2.3-canary.13", "amphtml-validator": "1.0.30", "async-retry": "1.2.3", "async-sema": "3.0.0",
url: {url}