Enable code splitting for the web runtime build (#31090)
When using the web runtime with SSR streaming, this PR significantly improves the build speed for large applications when there're large modules shared by most pages. With another optimization, `react-dom` will now be excluded in the web runtime build if it's imported in the application. It will only take effect in the client bundle. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] 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`
This commit is contained in:
parent
9e03c8d4ed
commit
feed67ee36
2 changed files with 37 additions and 18 deletions
|
@ -990,7 +990,12 @@ export default async function getBaseWebpackConfig(
|
|||
? // make sure importing "next" is handled gracefully for client
|
||||
// bundles in case a user imported types and it wasn't removed
|
||||
// TODO: should we warn/error for this instead?
|
||||
['next', ...(webServerRuntime ? [{ etag: '{}', chalk: '{}' }] : [])]
|
||||
[
|
||||
'next',
|
||||
...(webServerRuntime
|
||||
? [{ etag: '{}', chalk: '{}', 'react-dom': '{}' }]
|
||||
: []),
|
||||
]
|
||||
: !isServerless
|
||||
? [
|
||||
({
|
||||
|
@ -1054,10 +1059,10 @@ export default async function getBaseWebpackConfig(
|
|||
}
|
||||
: {}),
|
||||
splitChunks: isServer
|
||||
? dev || webServerRuntime
|
||||
? dev
|
||||
? false
|
||||
: ({
|
||||
filename: '[name].js',
|
||||
filename: webServerRuntime ? 'chunks/[name].js' : '[name].js',
|
||||
// allow to split entrypoints
|
||||
chunks: ({ name }: any) => !name?.match(MIDDLEWARE_ROUTE),
|
||||
// size of files is not so relevant for server build
|
||||
|
@ -1465,7 +1470,8 @@ export default async function getBaseWebpackConfig(
|
|||
new PagesManifestPlugin({ serverless: isLikeServerless, dev }),
|
||||
// MiddlewarePlugin should be after DefinePlugin so NEXT_PUBLIC_*
|
||||
// replacement is done before its process.env.* handling
|
||||
!isServer && new MiddlewarePlugin({ dev }),
|
||||
(!isServer || webServerRuntime) &&
|
||||
new MiddlewarePlugin({ dev, webServerRuntime }),
|
||||
isServer && new NextJsSsrImportPlugin(),
|
||||
!isServer &&
|
||||
new BuildManifestPlugin({
|
||||
|
|
|
@ -4,7 +4,6 @@ import { getSortedRoutes } from '../../../shared/lib/router/utils'
|
|||
import {
|
||||
MIDDLEWARE_MANIFEST,
|
||||
MIDDLEWARE_FLIGHT_MANIFEST,
|
||||
MIDDLEWARE_SSR_RUNTIME_WEBPACK,
|
||||
MIDDLEWARE_BUILD_MANIFEST,
|
||||
MIDDLEWARE_REACT_LOADABLE_MANIFEST,
|
||||
} from '../../../shared/lib/constants'
|
||||
|
@ -31,11 +30,25 @@ export interface MiddlewareManifest {
|
|||
}
|
||||
}
|
||||
|
||||
const middlewareManifest: MiddlewareManifest = {
|
||||
sortedMiddleware: [],
|
||||
clientInfo: [],
|
||||
middleware: {},
|
||||
version: 1,
|
||||
}
|
||||
export default class MiddlewarePlugin {
|
||||
dev: boolean
|
||||
webServerRuntime: boolean
|
||||
|
||||
constructor({ dev }: { dev: boolean }) {
|
||||
constructor({
|
||||
dev,
|
||||
webServerRuntime,
|
||||
}: {
|
||||
dev: boolean
|
||||
webServerRuntime: boolean
|
||||
}) {
|
||||
this.dev = dev
|
||||
this.webServerRuntime = webServerRuntime
|
||||
}
|
||||
|
||||
createAssets(
|
||||
|
@ -44,17 +57,14 @@ export default class MiddlewarePlugin {
|
|||
envPerRoute: Map<string, string[]>
|
||||
) {
|
||||
const entrypoints = compilation.entrypoints
|
||||
const middlewareManifest: MiddlewareManifest = {
|
||||
sortedMiddleware: [],
|
||||
clientInfo: [],
|
||||
middleware: {},
|
||||
version: 1,
|
||||
}
|
||||
|
||||
for (const entrypoint of entrypoints.values()) {
|
||||
if (!entrypoint.name) continue
|
||||
const result = MIDDLEWARE_FULL_ROUTE_REGEX.exec(entrypoint.name)
|
||||
|
||||
const ssrEntryInfo = ssrEntries.get(entrypoint.name)
|
||||
if (ssrEntryInfo && !this.webServerRuntime) continue
|
||||
if (!ssrEntryInfo && this.webServerRuntime) continue
|
||||
|
||||
const location = result
|
||||
? `/${result[1]}`
|
||||
|
@ -67,14 +77,15 @@ export default class MiddlewarePlugin {
|
|||
}
|
||||
const files = ssrEntryInfo
|
||||
? [
|
||||
`server/${MIDDLEWARE_SSR_RUNTIME_WEBPACK}.js`,
|
||||
ssrEntryInfo.requireFlightManifest
|
||||
? `server/${MIDDLEWARE_FLIGHT_MANIFEST}.js`
|
||||
: null,
|
||||
`server/${MIDDLEWARE_BUILD_MANIFEST}.js`,
|
||||
`server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js`,
|
||||
`server/${entrypoint.name}.js`,
|
||||
].filter(nonNullable)
|
||||
...entrypoint.getFiles().map((file) => 'server/' + file),
|
||||
]
|
||||
.filter(nonNullable)
|
||||
.filter((file: string) => !file.endsWith('.hot-update.js'))
|
||||
: entrypoint
|
||||
.getFiles()
|
||||
.filter((file: string) => !file.endsWith('.hot-update.js'))
|
||||
|
@ -106,9 +117,11 @@ export default class MiddlewarePlugin {
|
|||
}
|
||||
)
|
||||
|
||||
assets[`server/${MIDDLEWARE_MANIFEST}`] = new sources.RawSource(
|
||||
JSON.stringify(middlewareManifest, null, 2)
|
||||
)
|
||||
assets[
|
||||
this.webServerRuntime
|
||||
? MIDDLEWARE_MANIFEST
|
||||
: `server/${MIDDLEWARE_MANIFEST}`
|
||||
] = new sources.RawSource(JSON.stringify(middlewareManifest, null, 2))
|
||||
}
|
||||
|
||||
apply(compiler: webpack5.Compiler) {
|
||||
|
|
Loading…
Reference in a new issue