迁移 webpack

Rspack 的配置是基于 webpack 的设计实现的,以此你能够非常轻松地将项目从 webpack 迁移至 Rspack。

文档主要针对使用 webpack 5 的项目,因为目前 Rspack 的配置是基于 webpack 5 的设计实现的。如果你的项目使用的不是 webpack 5,可以参考以下迁移指南:

安装 Rspack

在你的项目目录下,安装 Rspack 为开发依赖:

npm
yarn
pnpm
bun
npm add @rspack/core @rspack/cli -D

现在你可以移除项目中 webpack 相关的依赖了:

npm
yarn
pnpm
bun
npm remove webpack webpack-cli webpack-dev-server
TIP

在个别情况下,你仍然需要保留 webpack 作为开发依赖,例如使用 vue-loader 时。

这是因为这些库直接 import 了 webpack 的子路径,与 webpack 产生了耦合。如果你遇到了这种情况,可以向这些插件的维护者反馈,询问他们能否将 webpack 作为可选依赖。

修改 package.json

更新构建脚本以使用 Rspack 代替 webpack:

package.json
{
  "scripts": {
-   "serve": "webpack serve",
-   "build": "webpack build",
+   "serve": "rspack serve",
+   "build": "rspack build",
  }
}

修改配置

webpack.config.js 文件重命名为 rspack.config.js

提示

Rspack 命令与 webpack 命令相同,均可通过 -c--config 指定配置文件。但与 webpack 不同的是,如果你未显式指定配置文件,Rspack 默认使用 rspack.config.js

Rspack 目前并不支持所有 webpack 配置,有些配置会影响构建产物,为保证构建产物的正确性,Rspack 默认开启了对配置的严格校验。 不过,Rspack 也提供了宽松模式,方便进行渐进式迁移。你可以通过设置 RSPACK_CONFIG_VALIDATE 环境变量来开启宽松模式:

# 开启宽松校验模式,会打印错误的配置但不会抛出错误
RSPACK_CONFIG_VALIDATE=loose rspack build
# 开启宽松校验模式,不打印错误也不抛出错误
RSPACK_CONFIG_VALIDATE=loose-silent rspack build

Rspack 正在积极推动 webpack 的下一个版本的功能,因此在部分配置项上与 webpack 5 的默认值不同,如下:

配置 webpack 默认值 Rspack 默认值
node.global true 'warn'
node.__filename 'mock' 'warn-mock'
node.__dirname 'mock' 'warn-mock'

查阅配置 Rspack 来了解 Rspack 支持的所有配置。

Webpack 内置插件

Rspack 实现了大部分 webpack 内置插件,其命名和参数配置与 webpack 保持一致,你可以非常轻松地替换它们。

例如替换 DefinePlugin

rspack.config.js
- const webpack = require('webpack');
+ const rspack = require('@rspack/core');

module.exports = {
  //...
  plugins: [
-   new webpack.DefinePlugin({
+   new rspack.DefinePlugin({
      // ...
    }),
  ],
}

查看同步自 webpack 的内置插件以了解 Rspack 对 webpack 所有内置插件的支持情况。

社区插件

Rspack 支持大部分 webpack 社区插件,并为暂不支持的插件提供了替代方案。

查看 Plugin 兼容 以了解 Rspack 对 webpack 常见社区插件的兼容情况。

copy-webpack-plugin

使用 rspack.CopyRspackPlugin 代替 copy-webpack-plugin

rspack.config.js
- const CopyWebpackPlugin = require('copy-webpack-plugin');
+ const rspack = require('@rspack/core');

module.exports = {
  plugins: [
-   new CopyWebpackPlugin({
+   new rspack.CopyRspackPlugin({
      // ...
    }),
  ]
}

mini-css-extract-plugin

使用 rspack.CssExtractRspackPlugin 代替 mini-css-extract-plugin

rspack.config.js
- const CssExtractWebpackPlugin = require('mini-css-extract-plugin');
+ const rspack = require('@rspack/core');

module.exports = {
  plugins: [
-   new CssExtractWebpackPlugin({
+   new rspack.CssExtractRspackPlugin({
      // ...
    }),
  ]
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
-         CssExtractWebpackPlugin.loader,
+         rspack.CssExtractRspackPlugin.loader,
          "css-loader"
        ],
+       type: 'javascript/auto'
      }
    ]
  }
}

tsconfig-paths-webpack-plugin

使用 resolve.tsConfig 代替 tsconfig-paths-webpack-plugin

rspack.config.js
- const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  resolve: {
-   plugins: [new TsconfigPathsPlugin({})]
+   tsConfig: {}
  }
}

fork-ts-checker-webpack-plugin

使用 ts-checker-rspack-plugin 代替 fork-ts-checker-webpack-plugin

rspack.config.js
- const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+ const { TsCheckerRspackPlugin } = require('ts-checker-rspack-plugin');

module.exports = {
  plugins: [
-   new ForkTsCheckerWebpackPlugin()
+   new TsCheckerRspackPlugin()
  ]
}

Loader

Rspack 已实现了与 Webpack 功能完全对齐的 loader 执行器,支持绝大多数 webpack loader,因此你可以直接使用现有的 loader 而无需修改。不过,为了获得最佳性能,我们仍建议进行以下迁移:

babel-loader / swc-loader → builtin:swc-loader

通过 builtin:swc-loader 使用 Rspack 内置的 swc-loader,相比于 babel-loader 和外置的 swc-loader,它不需要在 JavaScript 和 Rust 之间进行频繁的通信,从而具有最佳的性能。

如果你需要通过 babel 插件进行自定义转换逻辑,可以保留 babel-loader,但不建议对大量文件使用 babel-loader,因为这会导致显著的性能下降。

rspack.config.js
module.exports = {
   module: {
     rules: [
-      {
-        test: /\.tsx?$/i,
-        use: [
-          {
-            loader: 'babel-loader',
-            options: {
-              presets: ['@babel/preset-typescript'],
-            },
-          },
-        ],
-        test: /\.jsx?$/i,
-        use: [
-          {
-            loader: 'babel-loader',
-            options: {
-              presets: ['@babel/preset-react'],
-            },
-          },
-        ],
-      },
+      {
+        test: /\.(j|t)s$/,
+        exclude: [/[\\/]node_modules[\\/]/],
+        loader: 'builtin:swc-loader',
+        options: {
+          jsc: {
+            parser: {
+              syntax: 'typescript',
+            },
+            externalHelpers: true,
+            transform: {
+              react: {
+                runtime: 'automatic',
+                development: !prod,
+                refresh: !prod,
+              },
+            },
+          },
+          env: {
+            targets: 'Chrome >= 48',
+          },
+        },
+      },
+      {
+        test: /\.(j|t)sx$/,
+        loader: 'builtin:swc-loader',
+        exclude: [/[\\/]node_modules[\\/]/],
+        options: {
+          jsc: {
+            parser: {
+              syntax: 'typescript',
+              tsx: true,
+            },
+            transform: {
+              react: {
+                runtime: 'automatic',
+                development: !prod,
+                refresh: !prod,
+              },
+            },
+            externalHelpers: true,
+          },
+          env: {
+            targets: 'Chrome >= 48', // browser compatibility
+          },
+        },
+      },
     ],
   },
 };

file-loader / url-loader / raw-loader资源模块

Rspack 实现了 webpack 5 的资源模块,使用资源模块来代替 file-loaderurl-loaderraw-loader 以达到最佳的性能。

file-loader → asset/resource

rspack.config.js
module.exports = {
   module: {
     rules: [
-      {
-        test: /\.(png|jpe?g|gif)$/i,
-        use: ["file-loader"],
-      },
+      {
+        test: /\.(png|jpe?g|gif)$/i,
+        type: "asset/resource",
+      },
     ],
   },
 };

url-loader → asset/inline

rspack.config.js
module.exports = {
   module: {
     rules: [
-      {
-        test: /\.(png|jpe?g|gif)$/i,
-        use: ["url-loader"],
-      },
+      {
+        test: /\.(png|jpe?g|gif)$/i,
+        type: "asset/inline",
+      },
     ],
   },
 };

raw-loader → asset/source

rspack.config.js
module.exports = {
   module: {
     rules: [
-      {
-        test: /^BUILD_ID$/,
-        use: ["raw-loader",],
-      },
+      {
+        test: /^BUILD_ID$/,
+        type: "asset/source",
+      },
     ],
   },
 };