迁移 Webpack

本章节介绍如何将使用 webpack 的项目迁移到 Rspack。

当前文档主要面向使用 webpack v5 的项目。因为 Rspack 的 API 和配置是对齐 webpack v5 实现的,从 webpack v5 迁移到 Rspack 会相对容易。

对于非 webpack v5 的项目,有一些其他迁移指南可以参考:

注意事项

  • Rspack 支持的 Node.js 版本为 >= 16,如果你还在使用旧版本的 Node.js,请先升级版本。
  • Rspack 尽可能地兼容了 webpack 的常用 API 和配置,但是不可避免地存在一些不同,你可以阅读 Rspack 的文档来了解每个 API 和配置的差异。
  • 一部分功能在 Rspack 中有性能更好的实现方式,如果你采用 Rspack 推荐的方式,会获得更显著的性能提升。

安装依赖

首先你需要把 webpack 相关的 npm 依赖替换为 Rspack 的依赖。

  • 移除 webpack 的依赖:
npm
yarn
pnpm
bun
npm remove webpack webpack-cli webpack-dev-server
  • 安装 Rspack 的依赖:
npm
yarn
pnpm
bun
npm add @rspack/core @rspack/cli -D

以下是一些常见 npm 包的映射关系:

  • webpack -> @rspack/core
  • webpack-cli -> @rspack/cli
  • webpack-dev-server -> @rspack/dev-server
  • @pmmmwh/react-refresh-webpack-plugin -> @rspack/plugin-react-refresh

更新 npm scripts

下一步,你需要把 package.json 中的 npm scripts 更新为 Rspack 的 CLI 命令。

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

配置文件

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

Rspack 提供了与 webpack 相似的配置项,你可以参考 配置 Rspack 了解 Rspack 支持的配置。

内置插件

Rspack 实现了大部分 webpack 内置插件,它们尽可能地保持了相同的命名和参数配置,并提供相同的功能。

比如替换 HotModuleReplacementPlugin,原有配置如下:

webpack.config.js
const webpack = require('webpack');

const isDev = process.env.NODE_ENV === 'development';

module.exports = {
  plugins: [isDev && new webpack.HotModuleReplacementPlugin()].filter(Boolean),
};

在 Rspack 中可以替换为:

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

const isDev = process.env.NODE_ENV === 'development';

module.exports = {
  plugins: [isDev && new rspack.HotModuleReplacementPlugin()].filter(Boolean),
};

你可以参考 同步自 webpack 的内置插件 来了解 Rspack 支持哪些 webpack 内置插件。

社区插件

Rspack 支持大部分的 webpack 社区插件,同时也对一部分暂不支持的插件提供了替代方案。

你可以参考 Plugin 兼容 来了解 Rspack 对一些常见的社区插件的兼容状态。

处理 Loader

Rspack 支持大部分的 webpack loaders。下面列出了几个迁移 loader 的例子,参考这些例子进行替换,你可以获得更显著的性能提升。

使用 builtin:swc-loader 替代 babel-loader

Rspack 使用 builtin:swc-loader 对 TypeScript、JSX 以及最新的 JavaScript 语法进行转换,这意味着,如果你的 babel-loader 只是为了支持 TypeScript、JSX 以及更新的 JavaScript 语法,那么完全可以使用 builtin:swc-loader 替代 babel-loader。

如果你的 babel-loader 是为了支持自定义的转换逻辑,那么这部分的 babel-loader 可以保留,但是我们不鼓励用户对大量的文件使用 babel-loader,因为这会导致严重的性能劣化。

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
+          },
+        },
+      },
     ],
   },
 };

移除 css-loader 、 style-loader 和 mini-css-extract-plugin

Rspack 内置支持了 CSS 模块类型 ,原生 CSS 模块类型内置了对 CSS、CSS HMR、CSS Modules 以及 CSS 提取功能的支持,这意味着你不需要再为 CSS 文件单独配置 css-loader、style-loader 和 mini-css-extract-plugin。

-const MiniCssExtractPlugin = require("mini-css-extract-plugin");

 module.exports = {
   module: {
     rules: [
-      {
-        test: /\.css$/i,
-        use: [
-          isDev ? "style-loader" : MiniCssExtractPlugin.loader,
-          "css-loader",
-        ],
-      },
+      {
+        test: /\.css$/i,
+        type: "css", // this is enabled by default for .css, so you don't need to specify it
+      },
     ],
   },
   plugins: [],
 };

对于 css-modules 的功能,通过指明 css/module 作为模块类型即可开启。

module.exports = {
   module: {
     rules: [
+      {
+        test: /\.module\.css$/i,
+        type: "css/module", // this is enabled by default for module.css,   so you don't need to specify it
+      },
     ],
   },
 };

CssExtractPlugin

如果依赖 css-loader,例如 css-loader 提供的一些更加定制化的配置项,仍然可以使用 style-loader + css-loader 方案,如果你想要在生产环境将 CSS 提取成单独的文件,可以使用 Rspack 内置的 CssExtractRspackPlugin 插件。

CssExtractRspackPlugin 插件功能和配置与 mini-css-extract-plugin 类似,使用前请确保开启了 experiments.rspackFuture.newTreeshaking,v0.6 之后的版本默认开启。

+ const { CssExtractRspackPlugin } = require("@rspack/core");
- const CssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
+    new CssExtractRspackPlugin(),
-    new CssExtractPlugin(),
  ]
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
+          CssExtractRspackPlugin.loader,
-          CssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

使用 Asset Modules 来代替 file-loader、url-loader 和 raw-loader

Rspack 对齐 webpack 5 的 Asset Modules,这意味着你可以使用 Asset Modules 来代替 file-loader 和 url-loader。

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