Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dataRoutes field to routes-manifest for SSG and serverProps routes #10622

Merged
merged 4 commits into from Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 8 additions & 7 deletions packages/next/build/index.ts
Expand Up @@ -566,20 +566,21 @@ export default async function build(dir: string, conf = null): Promise<void> {
)
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',
buildId,
`${pagePath}.json`
)

routesManifest.serverPropsRoutes[page] = {
return {
page,
dataRouteRegex: isDynamicRoute(page)
? getRouteRegex(dataRoute.replace(/\.json$/, '')).re.source.replace(
Expand All @@ -594,7 +595,7 @@ export default async function build(dir: string, conf = null): Promise<void> {
)}$`
).source,
}
}
})

await fsWriteFile(
routesManifestPath,
Expand Down
31 changes: 31 additions & 0 deletions test/integration/dynamic-routing/test/index.test.js
Expand Up @@ -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

Expand Down Expand Up @@ -485,13 +486,43 @@ 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,
basePath: '',
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]',
Expand Down
98 changes: 53 additions & 45 deletions test/integration/getserverprops/test/index.test.js
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -208,15 +208,21 @@ 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'] })
})

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')
})
Expand All @@ -225,15 +231,18 @@ 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')
})

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')
})
Expand Down Expand Up @@ -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 () => {
Expand Down
77 changes: 77 additions & 0 deletions test/integration/prerender/test/index.test.js
Expand Up @@ -501,6 +501,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')
Expand Down