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

Update webpack server chunks output #22697

Merged
merged 8 commits into from
Mar 3, 2021
22 changes: 16 additions & 6 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ export default async function getBaseWebpackConfig(
splitChunks: isServer ? false : splitChunksConfig,
runtimeChunk: isServer
? isWebpack5 && !isLikeServerless
? { name: 'webpack-runtime' }
? { name: `${dev ? '' : 'chunks/'}webpack-runtime` }
: undefined
: { name: CLIENT_STATIC_FILES_RUNTIME_WEBPACK },
minimize: !(dev || isServer),
Expand Down Expand Up @@ -856,10 +856,15 @@ export default async function getBaseWebpackConfig(
},
}
: {}),
path: outputPath,
path:
isServer && isWebpack5 && !dev
? path.join(outputPath, 'chunks')
: outputPath,
// On the server we don't use the chunkhash
filename: isServer
? '[name].js'
? isWebpack5 && !dev
? '../[name].js'
: '[name].js'
: `static/chunks/[name]${dev ? '' : '-[chunkhash]'}.js`,
library: isServer ? undefined : '_N_E',
libraryTarget: isServer ? 'commonjs2' : 'assign',
Expand Down Expand Up @@ -1117,7 +1122,8 @@ export default async function getBaseWebpackConfig(
contextRegExp: /(next-server|next)[\\/]dist[\\/]/,
}),
isServerless && isServer && new ServerlessPlugin(),
isServer && new PagesManifestPlugin(isLikeServerless),
isServer &&
new PagesManifestPlugin({ serverless: isLikeServerless, dev }),
!isWebpack5 &&
target === 'server' &&
isServer &&
Expand All @@ -1141,8 +1147,12 @@ export default async function getBaseWebpackConfig(
(function () {
const {
FontStylesheetGatheringPlugin,
} = require('./webpack/plugins/font-stylesheet-gathering-plugin')
return new FontStylesheetGatheringPlugin()
} = require('./webpack/plugins/font-stylesheet-gathering-plugin') as {
FontStylesheetGatheringPlugin: typeof import('./webpack/plugins/font-stylesheet-gathering-plugin').FontStylesheetGatheringPlugin
}
return new FontStylesheetGatheringPlugin({
isLikeServerless,
})
})(),
config.experimental.conformance &&
!isWebpack5 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export class FontStylesheetGatheringPlugin {
compiler?: webpack.Compiler
gatheredStylesheets: Array<string> = []
manifestContent: FontManifest = []
isLikeServerless: boolean

constructor({ isLikeServerless }: { isLikeServerless: boolean }) {
this.isLikeServerless = isLikeServerless
}

private parserHandler = (
factory: webpack.compilation.NormalModuleFactory
Expand Down Expand Up @@ -137,8 +142,7 @@ export class FontStylesheetGatheringPlugin {
this.parserHandler
)
compiler.hooks.make.tapAsync(this.constructor.name, (compilation, cb) => {
// @ts-ignore
if (compilation.options.output.path.endsWith('serverless')) {
if (this.isLikeServerless) {
/**
* Inline font manifest for serverless case only.
* For target: server drive the manifest through physical file and less of webpack magic.
Expand Down Expand Up @@ -196,7 +200,7 @@ export class FontStylesheetGatheringPlugin {
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
},
(assets: any) => {
assets[FONT_MANIFEST] = new sources.RawSource(
assets['../' + FONT_MANIFEST] = new sources.RawSource(
JSON.stringify(this.manifestContent, null, ' ')
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,30 @@ class MiniCssExtractPlugin {

if (Object.keys(chunkMap).length > 0) {
const chunkMaps = chunk.getChunkMaps()
const { crossOriginLoading } = mainTemplate.outputOptions
const linkHrefPath = mainTemplate.getAssetPath(
const { crossOriginLoading } = isWebpack5
? compilation.outputOptions
: mainTemplate.outputOptions

const getHash = !isWebpack5
? (...args) => mainTemplate.renderCurrentHashCode(...args)
: (curHash, length) => {
if (length) {
return `${webpack.RuntimeGlobals.getFullHash} ? ${
webpack.RuntimeGlobals.getFullHash
}().slice(0, ${length}) : ${curHash.slice(0, length)}`
}
return `${webpack.RuntimeGlobals.getFullHash} ? ${webpack.RuntimeGlobals.getFullHash}() : ${curHash}`
}

const getAssetPath = isWebpack5
? (...args) => compilation.getAssetPath(...args)
: (...args) => mainTemplate.getAssetPath(...args)

const linkHrefPath = getAssetPath(
JSON.stringify(this.options.chunkFilename),
{
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
hashWithLength: (length) =>
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
hash: `" + ${getHash(hash)} + "`,
hashWithLength: (length) => `" + ${getHash(hash, length)} + "`,
chunk: {
id: '" + chunkId + "',
hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
Expand Down Expand Up @@ -286,7 +303,9 @@ class MiniCssExtractPlugin {
'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {',
Template.indent([
`var href = ${linkHrefPath};`,
`var fullhref = ${mainTemplate.requireFn}.p + href;`,
`var fullhref = ${
isWebpack5 ? '__webpack_require__' : mainTemplate.requireFn
}.p + href;`,
'var existingLinkTags = document.getElementsByTagName("link");',
'for(var i = 0; i < existingLinkTags.length; i++) {',
Template.indent([
Expand Down
17 changes: 12 additions & 5 deletions packages/next/build/webpack/plugins/pages-manifest-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export type PagesManifest = { [page: string]: string }
// It's also used by next export to provide defaultPathMap
export default class PagesManifestPlugin implements webpack.Plugin {
serverless: boolean
dev: boolean

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

createAssets(compilation: any, assets: any) {
Expand Down Expand Up @@ -45,12 +47,17 @@ export default class PagesManifestPlugin implements webpack.Plugin {
}

// Write filename, replace any backslashes in path (on windows) with forwardslashes for cross-platform consistency.
pages[pagePath] = files[0].replace(/\\/g, '/')
pages[pagePath] = files[0]

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

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

apply(compiler: webpack.Compiler): void {
Expand Down
4 changes: 4 additions & 0 deletions packages/next/next-server/server/config-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export async function shouldLoadWithWebpack5(
cwd: dir,
})

if (Number(process.env.NEXT_PRIVATE_TEST_WEBPACK5_MODE) > 0) {
return true
}

// No `next.config.js`:
if (!path?.length) {
return false // TODO: return true to default to webpack 5
Expand Down