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:
parent
ee266b9d9b
commit
482d78e1c2
3 changed files with 41 additions and 6 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue