ecd94c1a4d
This PR enables the generation of source maps for the bundled runtimes. This is fast enough that we can just use the optimal source map option directly. This is useful if you're having some errors in Next.js itself.
250 lines
7.8 KiB
JavaScript
250 lines
7.8 KiB
JavaScript
const webpack = require('webpack')
|
|
const path = require('path')
|
|
const TerserPlugin = require('terser-webpack-plugin')
|
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
|
|
|
const pagesExternals = [
|
|
'react',
|
|
'react/package.json',
|
|
'react/jsx-runtime',
|
|
'react/jsx-dev-runtime',
|
|
'react-dom',
|
|
'react-dom/package.json',
|
|
'react-dom/client',
|
|
'react-dom/server',
|
|
'react-dom/server.browser',
|
|
'react-dom/server.edge',
|
|
'react-server-dom-webpack/client',
|
|
'react-server-dom-webpack/client.edge',
|
|
'react-server-dom-webpack/server.edge',
|
|
'react-server-dom-webpack/server.node',
|
|
]
|
|
|
|
function makeAppAliases(reactChannel = '') {
|
|
return {
|
|
react$: `next/dist/compiled/react${reactChannel}`,
|
|
'react/shared-subset$': `next/dist/compiled/react${reactChannel}/react.shared-subset`,
|
|
'react-dom/server-rendering-stub$': `next/dist/compiled/react-dom${reactChannel}/server-rendering-stub`,
|
|
'react-dom$': `next/dist/compiled/react-dom${reactChannel}/server-rendering-stub`,
|
|
'react/jsx-runtime$': `next/dist/compiled/react${reactChannel}/jsx-runtime`,
|
|
'react/jsx-dev-runtime$': `next/dist/compiled/react${reactChannel}/jsx-dev-runtime`,
|
|
'react-dom/client$': `next/dist/compiled/react-dom${reactChannel}/client`,
|
|
'react-dom/server$': `next/dist/compiled/react-dom${reactChannel}/server`,
|
|
'react-dom/server.edge$': `next/dist/compiled/react-dom${reactChannel}/server.edge`,
|
|
'react-dom/server.browser$': `next/dist/compiled/react-dom${reactChannel}/server.browser`,
|
|
'react-server-dom-webpack/client$': `next/dist/compiled/react-server-dom-webpack${reactChannel}/client`,
|
|
'react-server-dom-webpack/client.edge$': `next/dist/compiled/react-server-dom-webpack${reactChannel}/client.edge`,
|
|
'react-server-dom-webpack/server.edge$': `next/dist/compiled/react-server-dom-webpack${reactChannel}/server.edge`,
|
|
'react-server-dom-webpack/server.node$': `next/dist/compiled/react-server-dom-webpack${reactChannel}/server.node`,
|
|
// optimisations to ignore the legacy build of react-dom/server
|
|
'./cjs/react-dom-server-legacy.browser.production.min.js': `next/dist/build/noop-react-dom-server-legacy`,
|
|
'./cjs/react-dom-server-legacy.browser.development.js': `next/dist/build/noop-react-dom-server-legacy`,
|
|
}
|
|
}
|
|
|
|
const appAliases = makeAppAliases()
|
|
const appExperimentalAliases = makeAppAliases('-experimental')
|
|
|
|
const sharedExternals = [
|
|
'styled-jsx',
|
|
'styled-jsx/style',
|
|
'@opentelemetry/api',
|
|
'next/dist/compiled/@next/react-dev-overlay/dist/middleware',
|
|
'next/dist/compiled/@ampproject/toolbox-optimizer',
|
|
'next/dist/compiled/edge-runtime',
|
|
'next/dist/compiled/@edge-runtime/ponyfill',
|
|
'next/dist/compiled/undici',
|
|
'next/dist/compiled/raw-body',
|
|
'next/dist/server/capsize-font-metrics.json',
|
|
'critters',
|
|
'next/dist/compiled/node-html-parser',
|
|
'next/dist/compiled/compression',
|
|
'next/dist/compiled/jsonwebtoken',
|
|
'next/dist/compiled/@opentelemetry/api',
|
|
'next/dist/compiled/@mswjs/interceptors/ClientRequest',
|
|
'next/dist/compiled/ws',
|
|
]
|
|
|
|
const externalsMap = {
|
|
'./web/sandbox': 'next/dist/server/web/sandbox',
|
|
}
|
|
|
|
const externalsRegexMap = {
|
|
'(.*)trace/tracer$': 'next/dist/server/lib/trace/tracer',
|
|
}
|
|
|
|
const bundleTypes = {
|
|
app: {
|
|
'app-page': path.join(
|
|
__dirname,
|
|
'dist/esm/server/future/route-modules/app-page/module.js'
|
|
),
|
|
'app-route': path.join(
|
|
__dirname,
|
|
'dist/esm/server/future/route-modules/app-route/module.js'
|
|
),
|
|
},
|
|
pages: {
|
|
pages: path.join(
|
|
__dirname,
|
|
'dist/esm/server/future/route-modules/pages/module.js'
|
|
),
|
|
'pages-api': path.join(
|
|
__dirname,
|
|
'dist/esm/server/future/route-modules/pages-api/module.js'
|
|
),
|
|
},
|
|
server: {
|
|
server: path.join(__dirname, 'dist/esm/server/next-server.js'),
|
|
},
|
|
}
|
|
|
|
module.exports = ({ dev, turbo, bundleType, experimental }) => {
|
|
const externalHandler = ({ context, request, getResolve }, callback) => {
|
|
;(async () => {
|
|
if (request.endsWith('.external')) {
|
|
const resolve = getResolve()
|
|
const resolved = await resolve(context, request)
|
|
const relative = path.relative(
|
|
path.join(__dirname, '..'),
|
|
resolved.replace('esm' + path.sep, '')
|
|
)
|
|
callback(null, `commonjs ${relative}`)
|
|
} else {
|
|
const regexMatch = Object.keys(externalsRegexMap).find((regex) =>
|
|
new RegExp(regex).test(request)
|
|
)
|
|
if (regexMatch) {
|
|
return callback(null, 'commonjs ' + externalsRegexMap[regexMatch])
|
|
}
|
|
callback()
|
|
}
|
|
})()
|
|
}
|
|
|
|
/** @type {webpack.Configuration} */
|
|
return {
|
|
entry: bundleTypes[bundleType],
|
|
target: 'node',
|
|
mode: 'production',
|
|
output: {
|
|
path: path.join(__dirname, 'dist/compiled/next-server'),
|
|
filename: `[name]${turbo ? '-turbo' : ''}${
|
|
experimental ? '-experimental' : ''
|
|
}.runtime.${dev ? 'dev' : 'prod'}.js`,
|
|
libraryTarget: 'commonjs2',
|
|
},
|
|
devtool: 'source-map',
|
|
optimization: {
|
|
moduleIds: 'named',
|
|
minimize: true,
|
|
concatenateModules: true,
|
|
minimizer: [
|
|
new TerserPlugin({
|
|
minify: TerserPlugin.swcMinify,
|
|
terserOptions: {
|
|
compress: {
|
|
dead_code: true,
|
|
// Zero means no limit.
|
|
passes: 0,
|
|
},
|
|
format: {
|
|
preamble: '',
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
plugins: [
|
|
new webpack.DefinePlugin({
|
|
'typeof window': JSON.stringify('undefined'),
|
|
'process.env.NEXT_MINIMAL': JSON.stringify('true'),
|
|
'this.serverOptions.experimentalTestProxy': JSON.stringify(false),
|
|
'this.minimalMode': JSON.stringify(true),
|
|
'this.renderOpts.dev': JSON.stringify(dev),
|
|
'process.env.NODE_ENV': JSON.stringify(
|
|
dev ? 'development' : 'production'
|
|
),
|
|
'process.env.NEXT_RUNTIME': JSON.stringify('nodejs'),
|
|
...(!dev ? { 'process.env.TURBOPACK': JSON.stringify(turbo) } : {}),
|
|
}),
|
|
!!process.env.ANALYZE &&
|
|
new BundleAnalyzerPlugin({
|
|
analyzerPort: calculateUniquePort(
|
|
dev,
|
|
turbo,
|
|
experimental,
|
|
bundleType
|
|
),
|
|
openAnalyzer: false,
|
|
}),
|
|
].filter(Boolean),
|
|
stats: {
|
|
optimizationBailout: true,
|
|
},
|
|
resolve: {
|
|
alias:
|
|
bundleType === 'app'
|
|
? experimental
|
|
? appExperimentalAliases
|
|
: appAliases
|
|
: {},
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
include: /vendored[\\/]rsc[\\/]entrypoints/,
|
|
resolve: {
|
|
conditionNames: ['react-server', '...'],
|
|
alias: {
|
|
react$: `next/dist/compiled/react${
|
|
experimental ? '-experimental' : ''
|
|
}/react.shared-subset`,
|
|
},
|
|
},
|
|
layer: 'react-server',
|
|
},
|
|
{
|
|
issuerLayer: 'react-server',
|
|
resolve: {
|
|
conditionNames: ['react-server', '...'],
|
|
alias: {
|
|
react$: `next/dist/compiled/react${
|
|
experimental ? '-experimental' : ''
|
|
}/react.shared-subset`,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
externals: [
|
|
...sharedExternals,
|
|
...(bundleType === 'pages' ? pagesExternals : []),
|
|
externalsMap,
|
|
externalHandler,
|
|
],
|
|
experiments: {
|
|
layers: true,
|
|
},
|
|
}
|
|
}
|
|
|
|
function calculateUniquePort(dev, turbo, experimental, bundleType) {
|
|
const devOffset = dev ? 1000 : 0
|
|
const turboOffset = turbo ? 200 : 0
|
|
const experimentalOffset = experimental ? 40 : 0
|
|
let bundleTypeOffset
|
|
|
|
switch (bundleType) {
|
|
case 'app':
|
|
bundleTypeOffset = 1
|
|
break
|
|
case 'pages':
|
|
bundleTypeOffset = 2
|
|
break
|
|
default:
|
|
bundleTypeOffset = 3
|
|
}
|
|
|
|
return 8888 + devOffset + turboOffset + experimentalOffset + bundleTypeOffset
|
|
}
|