close

从 v1 升级到 v2

当前文档列出了从 Rspack 1.x 到 2.0 的所有不兼容更新,你可以参考此文档来迁移。

使用 Agent Skills

如果你在使用支持 Skills 的 Coding Agent,可以安装 rspack-v2-upgrade 技能来辅助完成 v1 到 v2 的升级流程。

npx skills add rstackjs/agent-skills --skill rspack-v2-upgrade

安装后,让 Coding Agent 协助完成升级即可。

升级 Node.js

Rspack 2.0 的最低 Node.js 版本要求为 20.19+22.12+,并且不再支持 Node.js 18。

Pure ESM 包

@rspack/core@rspack/cli@rspack/dev-server 已以 pure ESM 形式发布,移除了 CommonJS 构建产物。

在 Node.js 20 及以上版本中,运行时已原生支持通过 require(esm) 加载 ESM 模块。因此,对大多数仍通过 JavaScript API 使用 Rspack 的项目来说,这一变更通常不会带来实际影响,也无需额外修改现有代码。

这一变更不影响 Rspack 构建 CommonJS 产物的能力,相关的构建行为和配置方式也保持不变。

开发服务器

@rspack/dev-server 发布了 2.0 版本,相关变更包括:

  • @rspack/cli 不再默认依赖 @rspack/dev-server,这是因为部分场景并不需要开发服务器,当你使用 rspack devrspack serve 命令时,请手动安装 @rspack/dev-server
npm
yarn
pnpm
bun
deno
npm add @rspack/dev-server@beta -D
  • 部分 devServer 选项发生了变更,包括 devServer.proxydevServer.watchFiles 等,参考 升级文档 了解更多。

@rspack/dev-server 的依赖变得更加精简和现代化:

产物分析

@rspack/cli 内置的 webpack-bundler-analyzer 已被移除,同时 --analyze 参数也将不再可用。

如果你需要分析产物体积,推荐使用分析能力更强的 Rsdoctor 来替代。

实验性配置变更

移除 experiments.css

experiments.css 已被移除。CSS 处理能力现在默认可用,但仍需要在 module.rules 中配置对应的 type 以启用:

rspack.config.mjs
export default {
  module: {
    rules: [
      {
        test: /\.css$/,
        type: 'css/auto', // 自动识别 CSS Modules
      },
    ],
  },
};

可用的 type 如下:

  • css:将 CSS 作为纯 CSS 处理,不启用 CSS Modules
  • css/module:强制启用 CSS Modules
  • css/auto:自动检测,对于 .module.css 文件启用 CSS Modules,普通 .css 文件则作为纯 CSS 处理

更多详情参考 CSS

默认启用 experiments.asyncWebAssembly

experiments.asyncWebAssembly 的默认值从 false 调整为 true。后缀为 .wasm 的文件将使用内置的 webassembly/async 规则处理。

如果不需要此功能,可以显式禁用:

rspack.config.mjs
export default {
  experiments: {
    asyncWebAssembly: false,
  },
};

移动 experiments.cache

experiments.cache 已移动到顶层的 cache

rspack.config.mjs
export default {
-  experiments: {
-    cache: {
-      type: 'filesystem',
-      buildDependencies: {
-        config: [__filename],
-      },
-    },
-  },
+  cache: {
+    type: 'filesystem',
+    buildDependencies: {
+      config: [__filename],
+    },
+  },
};

移除 experiments.rspackFuture

experiments.rspackFuture 已被移除,其中的 bundlerInfo 选项已移动到 output.bundlerInfo

rspack.config.mjs
export default {
-  experiments: {
-    rspackFuture: {
-      bundlerInfo: {
-        version: '1.0.0',
-      },
-    },
-  },
+  output: {
+    bundlerInfo: {
+      version: '1.0.0',
+    },
+  },
};

移动 experiments.incremental

experiments.incremental 已移动到顶层的 incremental

rspack.config.mjs
export default {
-  experiments: {
-    incremental: {
-      make: true,
-      emitAssets: true,
-    },
-  },
+  incremental: {
+    make: true,
+    emitAssets: true,
+  },
};

移除 experiments.layers

experiments.layers 已被移除。Layer 功能已稳定并默认可用,但仍需要在 module.rules 中配置 layer 以启用:

rspack.config.mjs
export default {
  module: {
    rules: [
      {
        test: /\.css$/,
        type: 'css/auto',
        layer: 'styles', // 将 CSS 模块放入 'styles' layer
      },
      {
        test: /\.js$/,
        layer: 'app', // 将 JS 模块放入 'app' layer
      },
    ],
  },
};

移除 experiments.topLevelAwait

experiments.topLevelAwait 已被移除。Top-level await 功能已稳定并默认启用,现在在 ESM 模块中使用 top-level await 将自动生效:

get-config.mjs
// 在模块顶层直接使用 await
const response = await fetch('https://api.example.com/config');
const config = await response.json();

export default config;

移除 experiments.lazyCompilation

experiments.lazyCompilation 已移动到顶层的 lazyCompilation

rspack.config.mjs
export default {
-  experiments: {
-    lazyCompilation: true,
-  },
+  lazyCompilation: true,
};

experiments.lazyCompilationMiddleware 已移动到顶层的 lazyCompilationMiddleware

rspack.config.mjs
- const middleware = rspack.experiments.lazyCompilationMiddleware(compiler);
+ const middleware = rspack.lazyCompilationMiddleware(compiler);

const server = new DevServer(
  {
    port: 3000,
    setupMiddlewares(other) {
      return [middleware, ...other];
    },
  },
  compiler,
);

移除 experiments.lazyBarrel

experiments.lazyBarrel 已被移除,Lazy barrel 优化将默认启用。

移除 experiments.typeReexportsPresence

experiments.typeReexportsPresence 已被移除,可使用 module.parser.javascript.typeReexportsPresence 控制类型重导出时的行为。

移除 experiments.inlineConst

experiments.inlineConst 已被移除,可使用 optimization.inlineExports 控制常量内联优化。

移除 experiments.inlineEnum

experiments.inlineEnum 已被移除,可使用 optimization.inlineExports 和 builtin:swc-loader 的 collectTypeScriptInfo.exportedEnum 控制枚举内联优化。

移除 experiments.outputModule

experiments.outputModule 已被移除,可使用 output.module 输出 ESM 产物。

移除 experiments.parallelLoader

experiments.parallelLoader 已被移除,Loader 并行化功能已稳定并默认可用,但仍需要在 module.rules[].use.parallel 中启用:

rspack.config.mjs
export default {
-  experiments: {
-    parallelLoader: true,
-  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: './my-loader.js',
            parallel: true, // 启用并行化 loader
          },
        ],
      },
    ],
  },
};

模块编译相关变更

修改 module.parser.javascript.exportsPresence 的默认值

module.parser.javascript.exportsPresence 的默认值由 warn 变更为 error。当检测到导出的内容不存在时,现在将直接抛出错误而不是仅仅警告。

如果你希望恢复为旧行为,可显式设置为 auto

rspack.config.mjs
export default {
  module: {
    parser: {
      javascript: {
        exportsPresence: 'auto',
      },
    },
  },
};

移除 module.parser.javascript.strictExportPresence

module.parser.javascript.strictExportPresence 已被移除,可使用 module.parser.javascript.exportsPresence 控制导出内容不存在时的行为。

修改 module.parser.javascript.requireAlias 的默认值

module.parser.javascript.requireAlias 的默认值从 true 调整为 false。当检测到 require 被赋值给变量或作为参数传递时,将不会进行解析和转换。

如果你的代码中使用了 require 重命名并加载了下游模块,同时希望该模块能够被打包到产物中,可显式启用:

rspack.config.mjs
export default {
  module: {
    parser: {
      javascript: {
        requireAlias: true,
      },
    },
  },
};

禁用 builtin:swc-loader 读取 .swcrc

在 Rspack 2.0 中,builtin:swc-loader 不再支持读取 .swcrc 文件。你需要将 SWC 配置迁移到 rspack.config.js 的 loader 选项中:

rspack.config.mjs
export default {
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'builtin:swc-loader',
        options: {
          jsc: {
            parser: {
              syntax: 'ecmascript',
              jsx: true,
            },
            transform: {
              react: {
                runtime: 'automatic',
              },
            },
          },
        },
      },
    ],
  },
};

移除 builtin:swc-loader 的 rspackExperiments.collectTypeScriptInfo

builtin:swc-loaderrspackExperiments.collectTypeScriptInfo 已被移除,可使用 collectTypeScriptInfo 控制 TypeScript 信息收集。

rspack.config.mjs
export default {
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'builtin:swc-loader',
        options: {
          collectTypeScriptInfo: {
            typeExports: true,
          },
        },
      },
    ],
  },
};

从 target 派生 loader 和 plugin 的 targets 配置

在 Rspack 2.0 中,builtin:swc-loaderbuiltin:lightningcss-loaderrspack.LightningCssMinimizerRspackPlugintargets 配置现在默认从 target 配置派生。

如果需要显式控制 targets 配置,可在 loader 或 plugin 选项中配置:

rspack.config.mjs
export default {
  target: 'node',
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'builtin:swc-loader',
        options: {
          env: {
            targets: 'chrome >= 87',
          },
        },
      },
    ],
  },
};

产物相关配置变更

移除 output.libraryTarget

output.libraryTarget 已被移动到 output.library.type

移除 output.libraryExport

output.libraryExport 已被移动到 output.library.export

移除 output.umdNamedDefine

output.umdNamedDefine 已被移动到 output.library.umdNamedDefine

移除 output.auxiliaryComment

output.auxiliaryComment 已被移动到 output.library.auxiliaryComment

修改 output.chunkLoadingGlobal 的默认值

output.chunkLoadingGlobal 的默认值从 webpackChunk${output.uniqueName} 改为 rspackChunk${output.uniqueName}

如果你的应用依赖特定的全局变量名称,可显式配置:

rspack.config.mjs
export default {
  output: {
    chunkLoadingGlobal: 'webpackChunkMyApp',
  },
};

修改 output.hotUpdateGlobal 的默认值

output.hotUpdateGlobal 的默认值从 webpackHotUpdate${output.uniqueName} 改为 rspackHotUpdate${output.uniqueName}

如果你的应用依赖特定的全局变量名称,可显式配置:

rspack.config.mjs
export default {
  output: {
    hotUpdateGlobal: 'webpackHotUpdateMyApp',
  },
};

修改 output.trustedTypes.policyName 的默认值

output.trustedTypes.policyName 的打底值从 'webpack' 改为 'rspack'

policyName 的默认值为 output.uniqueName,只有在未设置 uniqueName 时才会使用打底值。

如果你的项目未设置 uniqueName 并依赖特定的 Trusted Types 策略名称,需要更新你的 CSP 配置或显式设置:

rspack.config.mjs
export default {
  output: {
    trustedTypes: {
      policyName: 'webpack',
    },
  },
};

移除 output.charset

output.charset 配置已被移除。该选项用于在生成的 <script> 标签中添加 charset 属性,但现代浏览器已默认使用 UTF-8 编码,不再需要此配置。

移除 optimization.removeAvailableModules

optimization.removeAvailableModules 配置已被移除。该选项在 Rspack 中没有实际作用,可以直接从配置中移除:

rspack.config.mjs
export default {
  optimization: {
-   removeAvailableModules: true,
  },
};

Stats 相关变更

修改 stats.toJson() 的默认参数

stats.toJson() 方法在未传入参数时,以下字段的默认值调整为 false

  • modules: 模块信息
  • assets: 资源信息
  • chunks: chunk 信息
  • chunkGroups: chunk group 信息
  • entryPoints: 入口点信息

这意味着调用 stats.toJson() 时,默认不再包含这些详细信息,返回的对象更加精简。如果你需要获取详细信息,可以在调用 toJson() 时显式传入参数:

const statsData = stats.toJson({
  modules: true,
  assets: true,
  chunks: true,
  chunkGroups: true,
  entryPoints: true,
});

详细参数配置可参考 Stats

移除 profile 和 stats.profile 配置

顶层的 profile 配置和 stats.profile 配置已被移除,建议使用 Rsdoctor 进行性能分析:

rspack.config.mjs
export default {
-  profile: true,
  stats: {
-    profile: true,
  },
};

插件相关变更

移除 EsmLibraryPlugin

rspack.EsmLibraryPlugin 插件已被移除,可以通过配置 output.librarymodern-module 来生成 ESM 格式的产物:

rspack.config.mjs
-import { EsmLibraryPlugin } from '@rspack/core';

export default {
-  plugins: [new EsmLibraryPlugin()],
+  output: {
+    library: {
+      type: 'modern-module',
+    },
+  },
};

移除 experiments.SubResourceIntegrityPlugin

experiments.SubResourceIntegrityPlugin 已移动到顶层的 SubresourceIntegrityPlugin 中:

rspack.config.mjs
import rspack from '@rspack/core';

export default {
  output: {
    crossOriginLoading: 'anonymous',
  },
  plugins: [
-    new rspack.experiments.SubresourceIntegrityPlugin(),
+    new rspack.SubresourceIntegrityPlugin(),
  ],
};

移除 WarnCaseSensitiveModulesPlugin

WarnCaseSensitiveModulesPlugin 插件已被移除,可以使用 CaseSensitivePlugin 插件来检测大小写敏感的模块引用问题:

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  plugins: [
-    new rspack.WarnCaseSensitiveModulesPlugin(),
+    new rspack.CaseSensitivePlugin(),
  ],
};

移除插件的 getHooks 方法

部分插件的 getHooks 方法已被移除,请使用 getCompilationHooks 方法替代:

my-plugin.js
class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
-      const hooks = compiler.HtmlRspackPlugin.getHooks(compilation);
+      const hooks = compiler.HtmlRspackPlugin.getCompilationHooks(compilation);

      hooks.beforeEmit.tap('MyPlugin', (data, cb) => {
        // ...
      });
    });
  }
}

调整 HtmlRspackPlugin 配置项

HtmlRspackPluginsri 配置已被移除。

如果你需要 Subresource Integrity (SRI) 功能,可使用 SubresourceIntegrityPlugin 插件。

rspack.config.mjs
export default {
  plugins: [
    new rspack.HtmlRspackPlugin({
-     sri: "sha256",
    }),
+   new rspack.SubresourceIntegrityPlugin({
+     hashFuncNames: ["sha256"],
+   }),
  ],
};

调整 LightningCssMinimizerRspackPlugin 配置项

LightningCssMinimizerRspackPlugin 的以下选项已被移除:

移除 draft

draft 选项已被移除,可使用 drafts 配置替代。

rspack.config.mjs
import { LightningCssMinimizerRspackPlugin } from '@rspack/core';

export default {
  optimization: {
    minimizer: [
      new LightningCssMinimizerRspackPlugin({
-       draft: {
-         customMedia: true,
-       },
+       drafts: {
+         customMedia: true,
+       },
      }),
    ],
  },
};

移除 cssHeadDataCompression

cssHeadDataCompression 选项已被移除,你可以直接移除该选项,这不会影响构建结果。

rspack.config.mjs
import { LightningCssMinimizerRspackPlugin } from '@rspack/core';

export default {
  optimization: {
    minimizer: [
      new LightningCssMinimizerRspackPlugin({
-       cssHeadDataCompression: true,
      }),
    ],
  },
};

Resolve 行为变化

默认 extensions 变更

Rspack 2.0 默认用于 JavaScript 请求的 resolve.extensions 不再包含 .wasm

直接一点说,像 import './module'require('./module') 这种省略扩展名的请求,默认不再尝试解析到 ./module.wasm

import './module.wasm' 这样的显式导入不受影响。

如果你需要保留旧行为,可以在对应的 resolve.byDependency 配置中显式把 .wasm 加回去:

rspack.config.mjs
export default {
  resolve: {
    byDependency: {
      esm: {
        extensions: ['.js', '.json', '.wasm'],
      },
      commonjs: {
        extensions: ['.js', '.json', '.wasm'],
      },
    },
  },
};

CSS 解析 conditions

Rspack 2.0 默认的 CSS @import 解析 conditions 不再包含 webpack

如果你需要保留旧行为,可以显式把 webpack 加回去:

rspack.config.mjs
export default {
  resolve: {
    byDependency: {
      'css-import': {
        conditionNames: ['webpack', '...'],
      },
    },
  },
};

其他变更

devtool 默认值变化

devtool 选项的默认值发生了变化:

  • modedevelopment 时,将 devtool 的默认值从 eval 调整为 cheap-module-source-map
  • modeproduction 并使用 @rspack/cli 时,devtool 的默认值从 source-map 调整为 false

如果你需要在生产环境开启 source map,推荐设置为 source-maphidden-source-map

rspack.config.mjs
const isProd = process.env.NODE_ENV === 'production';

export default {
  devtool: isProd ? 'source-map' : 'cheap-module-source-map',
};

移除 Runtime module 废弃属性

Runtime module 的以下废弃属性已被移除:

  • constructorName - 构造函数名称属性
  • moduleIdentifier - 模块标识符属性

如果你在自定义插件中使用了这些属性,需要更新代码:

my-plugin.js
class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      compilation.hooks.runtimeModule.tap('MyPlugin', (module) => {
-       const name = module.constructorName;
-       const id = module.moduleIdentifier;
+       // 使用其他方式获取模块信息
+       const name = module.constructor.name;
+       const id = module.identifier();
      });
    });
  }
}

ProgressPlugin handler 签名变更

ProgressPlugin 自定义 handler 的第三个参数已从 items: string[] 变更为结构化的 info 对象。

- (percent, msg, items) => void
+ (percent, msg, info) => void

info 包含:

  • builtModules: number:已构建的模块数量
  • moduleIdentifier?: string:当前构建的模块标识符(仅在 build modules 更新阶段提供)

修改 resolve.roots 的默认值

resolve 的 roots 配置默认值已从 [ context ] 变更为 []

如果你依赖服务器相对 URL 解析,且期望路径相对于 roots 目录进行解析,可显式恢复原有行为:

rspack.config.mjs
export default {
  resolve: {
    roots: [context], // rspack 配置文件的 context 路径
  },
};

移除 readResourceForScheme hook

NormalModule.getCompilationHooks(compilation).readResourceForScheme 已被移除。这个 hook 只是 readResource.for(scheme) 的旧别名,请改用后者。

@module-federation/runtime-tools 声明为可选 peerDependency

@module-federation/runtime-tools 包已从 dependencies 调整为可选 peerDependencies(通过 peerDependencies + peerDependenciesMeta.optional 声明)。如果你使用了 ModuleFederationPlugin,请确保在你的项目中显式安装该包。