From 21661427d772b62974ab8ca9485dbbdcee9d5c56 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 20 Feb 2020 19:40:59 -0600 Subject: [PATCH 1/2] Add dataRoutes field to routes-manifest for SSG and serverProps routes --- packages/next/build/index.ts | 15 +-- .../getserverprops/test/index.test.js | 98 ++++++++++--------- test/integration/prerender/test/index.test.js | 77 +++++++++++++++ 3 files changed, 138 insertions(+), 52 deletions(-) diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 7eb4ccd70189ed2..8149a856c46f837 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -566,12 +566,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', @@ -579,7 +580,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( @@ -594,7 +595,7 @@ export default async function build(dir: string, conf = null): Promise { )}$` ).source, } - } + }) await fsWriteFile( routesManifestPath, diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 1c932da181e2a68..760db33379a1b63 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -24,72 +24,72 @@ let app let appPort let buildId -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 () => { @@ -208,7 +208,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'] }) @@ -216,7 +219,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') }) @@ -225,7 +231,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') @@ -233,7 +239,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') }) @@ -341,15 +350,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 15cc1629d39d243..d47e7b47f6645b1 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -474,6 +474,83 @@ const runTests = (dev = false) => { expect(initialHtml).toMatch(/hello.*?world/) }) + 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 dbbfab3a544607e0b901a69acb09fd29783192a5 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 20 Feb 2020 20:03:07 -0600 Subject: [PATCH 2/2] Update routes-manifest test --- .../dynamic-routing/test/index.test.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/integration/dynamic-routing/test/index.test.js b/test/integration/dynamic-routing/test/index.test.js index 77978c4e95cb42a..4c73f4430f5507c 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]',