Skip to content

Commit 04c3f0b

Browse files
authored
Update bundler for pre-bundling runtime (#75294)
This improves the build script quite a bit and makes dev editing much faster. Also fixed excludes causing webpack/babel compiled packages to be bundled into the runtime un-necessarily reducing from `10MB` -> `1.2MB`. Before: `Finished next_bundle in 9.67s` After: `Finished next_bundle in 1.27s` Validated here https://github.com/vercel/vercel/actions/runs/12957911052/job/36147343396?pr=12914
1 parent 47a0cd2 commit 04c3f0b

File tree

11 files changed

+229
-84
lines changed

11 files changed

+229
-84
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
"files": ["packages/**"],
163163
"excludedFiles": [
164164
"packages/next/taskfile*.js",
165-
"packages/next/next-runtime.webpack-config.js"
165+
"packages/next/next_runtime.config.js"
166166
],
167167
"rules": {
168168
"no-shadow": ["error", { "builtinGlobals": false }],

packages/next/next-runtime.webpack-config.js renamed to packages/next/next_runtime.config.js

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
const webpack = require('webpack')
1+
const webpack = require('@rspack/core')
22
const path = require('path')
3-
const TerserPlugin = require('terser-webpack-plugin')
43
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
5-
const EvalSourceMapDevToolPlugin = require('./webpack-plugins/eval-source-map-dev-tool-plugin')
64
const DevToolsIgnoreListPlugin = require('./webpack-plugins/devtools-ignore-list-plugin')
75

8-
function shouldIgnorePath(modulePath) {
6+
function shouldIgnorePath() {
97
// For consumers, everything will be considered 3rd party dependency if they use
108
// the bundles we produce here.
119
// In other words, this is all library code and should therefore be ignored.
@@ -130,6 +128,11 @@ const bundleTypes = {
130128
module.exports = ({ dev, turbo, bundleType, experimental }) => {
131129
const externalHandler = ({ context, request, getResolve }, callback) => {
132130
;(async () => {
131+
if (request.match(/next[/\\]dist[/\\]compiled[/\\](babel|webpack)/)) {
132+
callback(null, 'commonjs ' + request)
133+
return
134+
}
135+
133136
if (request.endsWith('.external')) {
134137
const resolve = getResolve()
135138
const resolved = await resolve(context, request)
@@ -156,44 +159,23 @@ module.exports = ({ dev, turbo, bundleType, experimental }) => {
156159
return {
157160
entry: bundleTypes[bundleType],
158161
target: 'node',
159-
mode: 'production',
162+
mode: dev ? 'development' : 'production',
160163
output: {
161164
path: path.join(__dirname, 'dist/compiled/next-server'),
162165
filename: `[name]${turbo ? '-turbo' : ''}${
163166
experimental ? '-experimental' : ''
164167
}.runtime.${dev ? 'dev' : 'prod'}.js`,
165168
libraryTarget: 'commonjs2',
166169
},
167-
devtool: process.env.NEXT_SERVER_EVAL_SOURCE_MAPS
168-
? // We'll use a fork in plugins
169-
false
170-
: 'source-map',
170+
devtool: 'source-map',
171171
optimization: {
172172
moduleIds: 'named',
173173
minimize: true,
174174
concatenateModules: true,
175-
minimizer: [
176-
new TerserPlugin({
177-
minify: TerserPlugin.swcMinify,
178-
terserOptions: {
179-
compress: {
180-
dead_code: true,
181-
// Zero means no limit.
182-
passes: 0,
183-
},
184-
format: {
185-
preamble: '',
186-
},
187-
mangle:
188-
dev && !process.env.NEXT_SERVER_EVAL_SOURCE_MAPS ? false : true,
189-
},
190-
}),
191-
],
175+
minimizer: [new webpack.SwcJsMinimizerRspackPlugin()],
192176
},
193177
plugins: [
194-
process.env.NEXT_SERVER_EVAL_SOURCE_MAPS
195-
? new EvalSourceMapDevToolPlugin({ shouldIgnorePath })
196-
: new DevToolsIgnoreListPlugin({ shouldIgnorePath }),
178+
new DevToolsIgnoreListPlugin({ shouldIgnorePath }),
197179
new webpack.DefinePlugin({
198180
'typeof window': JSON.stringify('undefined'),
199181
'process.env.NEXT_MINIMAL': JSON.stringify('true'),

packages/next/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"next": "./dist/bin/next"
8181
},
8282
"scripts": {
83-
"dev": "cross-env NEXT_SERVER_EVAL_SOURCE_MAPS=1 taskr",
83+
"dev": "taskr",
8484
"release": "taskr release",
8585
"build": "pnpm release",
8686
"prepublishOnly": "cd ../../ && turbo run build",
@@ -92,7 +92,7 @@
9292
},
9393
"taskr": {
9494
"requires": [
95-
"./taskfile-webpack.js",
95+
"./taskfile-rspack.js",
9696
"./taskfile-ncc.js",
9797
"./taskfile-swc.js",
9898
"./taskfile-watch.js"
@@ -171,6 +171,7 @@
171171
"@next/swc": "15.2.0-canary.25",
172172
"@opentelemetry/api": "1.6.0",
173173
"@playwright/test": "1.41.2",
174+
"@rspack/core": "1.2.2",
174175
"@storybook/addon-essentials": "^8.4.7",
175176
"@storybook/addon-interactions": "^8.4.7",
176177
"@storybook/addon-onboarding": "^8.4.7",

packages/next/src/compiled/sass-loader/cjs.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/next/src/server/next-server.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,9 +1330,12 @@ export default class NextNodeServer extends BaseServer<
13301330
}
13311331

13321332
protected getMiddlewareManifest(): MiddlewareManifest | null {
1333-
if (this.minimalMode) return null
1334-
const manifest: MiddlewareManifest = require(this.middlewareManifestPath)
1335-
return manifest
1333+
if (this.minimalMode) {
1334+
return null
1335+
} else {
1336+
const manifest: MiddlewareManifest = require(this.middlewareManifestPath)
1337+
return manifest
1338+
}
13361339
}
13371340

13381341
/** Returns the middleware routing item if there is one. */

packages/next/taskfile-webpack.js renamed to packages/next/taskfile-rspack.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
const webpack = require('webpack')
1+
const rspack = require('@rspack/core')
22

33
module.exports = function (task) {
44
// eslint-disable-next-line require-yield
5-
task.plugin('webpack', {}, function* (_, options) {
5+
task.plugin('rspack', {}, function* (_, options) {
66
options = options || {}
77

8-
const compiler = webpack(options.config)
8+
const compiler = rspack(options.config)
99

1010
if (options.watch) {
1111
return compiler.watch({}, (err, stats) => {
@@ -21,15 +21,15 @@ module.exports = function (task) {
2121
compiler.run((err, stats) => {
2222
if (err || stats.hasErrors()) {
2323
return this.emit('plugin_error', {
24-
plugin: 'taskfile-webpack',
24+
plugin: 'taskfile-rspack',
2525
error: err?.message ?? stats.toString(),
2626
})
2727
}
2828

2929
if (stats.hasWarnings()) {
3030
this.emit('plugin_warning', {
31-
plugin: 'taskfile-webpack',
32-
warning: `webpack compiled ${options.name} with warnings:\n${stats.toString('errors-warnings')}`,
31+
plugin: 'taskfile-rspack',
32+
warning: `rspack compiled ${options.name} with warnings:\n${stats.toString('errors-warnings')}`,
3333
})
3434
}
3535

packages/next/taskfile.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2846,9 +2846,9 @@ export async function release(task) {
28462846
}
28472847

28482848
export async function next_bundle_app_turbo(task, opts) {
2849-
await task.source('dist').webpack({
2849+
await task.source('dist').rspack({
28502850
watch: opts.dev,
2851-
config: require('./next-runtime.webpack-config')({
2851+
config: require('./next_runtime.config')({
28522852
turbo: true,
28532853
bundleType: 'app',
28542854
}),
@@ -2857,9 +2857,9 @@ export async function next_bundle_app_turbo(task, opts) {
28572857
}
28582858

28592859
export async function next_bundle_app_prod(task, opts) {
2860-
await task.source('dist').webpack({
2860+
await task.source('dist').rspack({
28612861
watch: opts.dev,
2862-
config: require('./next-runtime.webpack-config')({
2862+
config: require('./next_runtime.config')({
28632863
dev: false,
28642864
bundleType: 'app',
28652865
}),
@@ -2868,9 +2868,9 @@ export async function next_bundle_app_prod(task, opts) {
28682868
}
28692869

28702870
export async function next_bundle_app_dev(task, opts) {
2871-
await task.source('dist').webpack({
2871+
await task.source('dist').rspack({
28722872
watch: opts.dev,
2873-
config: require('./next-runtime.webpack-config')({
2873+
config: require('./next_runtime.config')({
28742874
dev: true,
28752875
bundleType: 'app',
28762876
}),
@@ -2879,9 +2879,9 @@ export async function next_bundle_app_dev(task, opts) {
28792879
}
28802880

28812881
export async function next_bundle_app_turbo_experimental(task, opts) {
2882-
await task.source('dist').webpack({
2882+
await task.source('dist').rspack({
28832883
watch: opts.dev,
2884-
config: require('./next-runtime.webpack-config')({
2884+
config: require('./next_runtime.config')({
28852885
turbo: true,
28862886
bundleType: 'app',
28872887
experimental: true,
@@ -2891,9 +2891,9 @@ export async function next_bundle_app_turbo_experimental(task, opts) {
28912891
}
28922892

28932893
export async function next_bundle_app_prod_experimental(task, opts) {
2894-
await task.source('dist').webpack({
2894+
await task.source('dist').rspack({
28952895
watch: opts.dev,
2896-
config: require('./next-runtime.webpack-config')({
2896+
config: require('./next_runtime.config')({
28972897
dev: false,
28982898
bundleType: 'app',
28992899
experimental: true,
@@ -2903,9 +2903,9 @@ export async function next_bundle_app_prod_experimental(task, opts) {
29032903
}
29042904

29052905
export async function next_bundle_app_dev_experimental(task, opts) {
2906-
await task.source('dist').webpack({
2906+
await task.source('dist').rspack({
29072907
watch: opts.dev,
2908-
config: require('./next-runtime.webpack-config')({
2908+
config: require('./next_runtime.config')({
29092909
dev: true,
29102910
bundleType: 'app',
29112911
experimental: true,
@@ -2915,9 +2915,9 @@ export async function next_bundle_app_dev_experimental(task, opts) {
29152915
}
29162916

29172917
export async function next_bundle_pages_prod(task, opts) {
2918-
await task.source('dist').webpack({
2918+
await task.source('dist').rspack({
29192919
watch: opts.dev,
2920-
config: require('./next-runtime.webpack-config')({
2920+
config: require('./next_runtime.config')({
29212921
dev: false,
29222922
bundleType: 'pages',
29232923
}),
@@ -2926,9 +2926,9 @@ export async function next_bundle_pages_prod(task, opts) {
29262926
}
29272927

29282928
export async function next_bundle_pages_dev(task, opts) {
2929-
await task.source('dist').webpack({
2929+
await task.source('dist').rspack({
29302930
watch: opts.dev,
2931-
config: require('./next-runtime.webpack-config')({
2931+
config: require('./next_runtime.config')({
29322932
dev: true,
29332933
bundleType: 'pages',
29342934
}),
@@ -2937,9 +2937,9 @@ export async function next_bundle_pages_dev(task, opts) {
29372937
}
29382938

29392939
export async function next_bundle_pages_turbo(task, opts) {
2940-
await task.source('dist').webpack({
2940+
await task.source('dist').rspack({
29412941
watch: opts.dev,
2942-
config: require('./next-runtime.webpack-config')({
2942+
config: require('./next_runtime.config')({
29432943
turbo: true,
29442944
bundleType: 'pages',
29452945
}),
@@ -2948,9 +2948,9 @@ export async function next_bundle_pages_turbo(task, opts) {
29482948
}
29492949

29502950
export async function next_bundle_server(task, opts) {
2951-
await task.source('dist').webpack({
2951+
await task.source('dist').rspack({
29522952
watch: opts.dev,
2953-
config: require('./next-runtime.webpack-config')({
2953+
config: require('./next_runtime.config')({
29542954
dev: false,
29552955
bundleType: 'server',
29562956
}),

packages/next/webpack-plugins/devtools-ignore-list-plugin.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Source: https://github.com/mondaychen/devtools-ignore-webpack-plugin/blob/e35ce41d9606a92a455ef247f509a1c2ccab5778/src/index.ts
22

33
// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file
4-
const webpack = require('webpack')
4+
const webpack = require('@rspack/core')
55

66
// Following the naming conventions from
77
// https://tc39.es/source-map/#source-map-format
@@ -28,12 +28,12 @@ module.exports = class DevToolsIgnorePlugin {
2828
}
2929
}
3030
apply(compiler) {
31-
const { RawSource } = compiler.webpack.sources
31+
const { RawSource } = webpack.sources
3232
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
3333
compilation.hooks.processAssets.tap(
3434
{
3535
name: PLUGIN_NAME,
36-
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
36+
stage: compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
3737
additionalAssets: true,
3838
},
3939
(assets) => {

0 commit comments

Comments
 (0)