Skip to content

Commit

Permalink
Ensure that pages manifest contains pages of both runtimes (#35243)
Browse files Browse the repository at this point in the history
Previously we only run `PagesManifestPlugin` in the Node server runtime, because the Edge target doesn't need it as the web server and middleware SSR loader specially handled pages manifest. This cases entrypoints with the Edge runtime configured being missing from there and this PR fixes it.

Part of #31317 and #31506.

## Bug

- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [ ] Errors have helpful link attached, see `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`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`
  • Loading branch information
shuding committed Mar 11, 2022
1 parent e57d621 commit 2b13c2f
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 7 deletions.
7 changes: 5 additions & 2 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1439,8 +1439,11 @@ export default async function getBaseWebpackConfig(
}),
((isServerless && isServer) || isEdgeRuntime) && new ServerlessPlugin(),
isServer &&
!isEdgeRuntime &&
new PagesManifestPlugin({ serverless: isLikeServerless, dev }),
new PagesManifestPlugin({
serverless: isLikeServerless,
dev,
isEdgeRuntime,
}),
// MiddlewarePlugin should be after DefinePlugin so NEXT_PUBLIC_*
// replacement is done before its process.env.* handling
(!isServer || isEdgeRuntime) &&
Expand Down
41 changes: 37 additions & 4 deletions packages/next/build/webpack/plugins/pages-manifest-plugin.ts
Expand Up @@ -4,16 +4,29 @@ import getRouteFromEntrypoint from '../../../server/get-route-from-entrypoint'

export type PagesManifest = { [page: string]: string }

let edgeServerPages = {}
let nodeServerPages = {}

// This plugin creates a pages-manifest.json from page entrypoints.
// This is used for mapping paths like `/` to `.next/server/static/<buildid>/pages/index.js` when doing SSR
// It's also used by next export to provide defaultPathMap
export default class PagesManifestPlugin implements webpack.Plugin {
serverless: boolean
dev: boolean
isEdgeRuntime: boolean

constructor({ serverless, dev }: { serverless: boolean; dev: boolean }) {
constructor({
serverless,
dev,
isEdgeRuntime,
}: {
serverless: boolean
dev: boolean
isEdgeRuntime: boolean
}) {
this.serverless = serverless
this.dev = dev
this.isEdgeRuntime = isEdgeRuntime
}

createAssets(compilation: any, assets: any) {
Expand All @@ -40,13 +53,33 @@ export default class PagesManifestPlugin implements webpack.Plugin {
pages[pagePath] = files[files.length - 1]

if (!this.dev) {
pages[pagePath] = pages[pagePath].slice(3)
if (!this.isEdgeRuntime) {
pages[pagePath] = pages[pagePath].slice(3)
}
}
pages[pagePath] = pages[pagePath].replace(/\\/g, '/')
}

assets[`${!this.dev ? '../' : ''}` + PAGES_MANIFEST] =
new sources.RawSource(JSON.stringify(pages, null, 2))
// This plugin is used by both the Node server and Edge server compilers,
// we need to merge both pages to generate the full manifest.
if (this.isEdgeRuntime) {
edgeServerPages = pages
} else {
nodeServerPages = pages
}

assets[
`${!this.dev && !this.isEdgeRuntime ? '../' : ''}` + PAGES_MANIFEST
] = new sources.RawSource(
JSON.stringify(
{
...edgeServerPages,
...nodeServerPages,
},
null,
2
)
)
}

apply(compiler: webpack.Compiler): void {
Expand Down
@@ -1,6 +1,10 @@
import { renderViaHTTP } from 'next-test-utils'
import { join } from 'path'
import fs from 'fs-extra'

export default async function runtime(context, { runtime }) {
import { distDir } from './utils'

export default async function runtime(context, { runtime, env }) {
if (runtime === 'edge') {
it('should support per-page runtime configuration', async () => {
const html1 = await renderViaHTTP(context.appPort, '/runtime')
Expand All @@ -9,4 +13,31 @@ export default async function runtime(context, { runtime }) {
expect(html2).toContain('Runtime: Node.js')
})
}
if (runtime === 'edge' && env === 'prod') {
it('should include entrypoints from both runtimes in pages manifest', async () => {
const distServerDir = join(distDir, 'server')
const pagesManifest = await fs.readJSON(
join(distServerDir, 'pages-manifest.json')
)

for (const key of [
// Defaults:
'/_app',
'/_error',
'/_document',
// Special:
'/404',
// API routes:
'/api/ping',
// Edge runtime pages:
'/streaming',
'/streaming-rsc',
// Node runtime pages:
'/runtime',
'/runtime-rsc',
]) {
expect(key in pagesManifest).toBeTruthy()
}
})
}
}

0 comments on commit 2b13c2f

Please sign in to comment.