Fix: fix pages in Route Groups returning 500 with output: "standalone" (#43746)

<!--
Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change that you're making:
-->

Fixes [#43367
(comment)](https://github.com/vercel/next.js/issues/43367#issuecomment-1338617317)

This fixes the issue in which pages that are in Route Groups return
status code 500 when built with `output: "standalone"` because of the
lack of required chunks in `.next/standalone/.next/server/chunks` by
handling their `.nft.json` files properly through using their
denormalized page paths, rather than their normalized ones to resolve
those files in `copyTracedFiles`.

## Bug

- [x] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ]
[e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
This commit is contained in:
Ngô Đức Anh 2022-12-13 10:06:40 +07:00 committed by GitHub
parent ee266b9d9b
commit 482d78e1c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 6 deletions

View file

@ -536,6 +536,7 @@ export default async function build(
)
let mappedAppPages: { [page: string]: string } | undefined
let denormalizedAppPages: string[] | undefined
if (appPaths && appDir) {
mappedAppPages = nextBuildSpan
@ -586,7 +587,8 @@ export default async function build(
const conflictingAppPagePaths: [pagePath: string, appPath: string][] = []
const appPageKeys: string[] = []
if (mappedAppPages) {
for (const appKey in mappedAppPages) {
denormalizedAppPages = Object.keys(mappedAppPages)
for (const appKey of denormalizedAppPages) {
const normalizedAppPageKey = normalizeAppPath(appKey) || '/'
const pagePath = mappedPages[normalizedAppPageKey]
if (pagePath) {
@ -596,7 +598,6 @@ export default async function build(
appPath.replace(/^private-next-app-dir/, 'app'),
])
}
appPageKeys.push(normalizedAppPageKey)
}
}
@ -2068,7 +2069,7 @@ export default async function build(
dir,
distDir,
pageKeys.pages,
pageKeys.app,
denormalizedAppPages,
outputFileTracingRoot,
requiredServerFiles.config,
middlewareManifest

View file

@ -1597,7 +1597,7 @@ export function detectConflictingPaths(
export async function copyTracedFiles(
dir: string,
distDir: string,
pageKeys: ReadonlyArray<string>,
pageKeys: readonly string[],
appPageKeys: readonly string[] | undefined,
tracingRoot: string,
serverConfig: { [key: string]: any },
@ -1712,7 +1712,7 @@ export async function copyTracedFiles(
if (middlewareManifest.functions.hasOwnProperty(page)) {
continue
}
const pageFile = path.join(distDir, 'server', 'app', `${page}`, 'page.js')
const pageFile = path.join(distDir, 'server', 'app', `${page}.js`)
const pageTraceFile = `${pageFile}.nft.json`
await handleTraceFiles(pageTraceFile).catch((err) => {
Log.warn(`Failed to copy traced files for ${pageFile}`, err)

View file

@ -40,10 +40,39 @@ describe('output: standalone with app dir', () => {
await next.destroy()
})
if ((global as any).isNextStart) {
it('should handle trace files correctly for route groups (nodejs only)', async () => {
expect(next.cliOutput).not.toContain('Failed to copy traced files')
const serverDirPath = path.join(
next.testDir,
'.next/standalone/.next/server'
)
for (const page of [
'(newroot)/dashboard/another',
'(newroot)/dashboard/project/[projectId]',
'(rootonly)/dashboard/changelog',
]) {
const pagePath = path.join(serverDirPath, 'app', page)
expect(
await fs.pathExists(path.join(pagePath, 'page.js.nft.json'))
).toBe(true)
const files = (
await fs.readJSON(path.join(pagePath, 'page.js.nft.json'))
).files as string[]
for (const file of files) {
expect(await fs.pathExists(path.join(pagePath, file))).toBe(true)
}
}
})
}
it('should work correctly with output standalone', async () => {
const tmpFolder = path.join(os.tmpdir(), 'next-standalone-' + Date.now())
await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder)
let server
let server: any
try {
const testServer = path.join(tmpFolder, 'server.js')
@ -66,7 +95,12 @@ describe('output: standalone with app dir', () => {
'/api/hello',
'/blog/first',
'/dashboard',
'/dashboard/another',
'/dashboard/changelog',
'/dashboard/deployments/breakdown',
'/dashboard/deployments/123',
'/dashboard/hello',
'/dashboard/project/123',
'/catch-all/first',
]) {
const res = await fetchViaHTTP(appPort, testPath)