宣布 Rspack 0.5

2024 年 1 月 9 日

主要功能更新

模块联邦已添加到 Rspack

查看这篇博客了解更多详情。

重大变更

optimization.chunkIds 在生产模式下默认情况下是确定性的

在生产模式下,optimization.chunkIds 现在为 "deterministic",这与 webpack 的默认行为一致。

支持 rspack.HotModuleReplacementPlugin

在 Rspack 中支持 rspack.HotModuleReplacementPlugin。如果您没有使用 @rspack/dev-server 并使用自定义开发服务器,您需要应用 HotModuleReplacementPlugin 来启用 HMR,而不是将 devServer.hot 设置为 true,这与 webpack 中的行为相同。这提供了与内部使用 HotModuleReplacementPlugin 的插件的更多兼容性。

删除默认转换

默认转换是一个内置功能,它在内部将源文件(如 TypeScript)转换为兼容的源文件(如 JavaScript)。为了使转换更具可定制性,我们通过使用 builtin:swc-loader 将此功能交给了用户,并删除了对几个rule.type 的支持。这些 rule.type 已被删除

  • "typescript""ts"
  • "tsx"
  • "jsx"

为了实现旧的行为,请删除 rule.type 或将其更改为 "javascript/auto" 并应用您的自定义加载器配置。

要转换 .jsx 文件

module.exports = {
  module: {
    rules: [
      {
        test: /\.jsx$/,
        exclude: /[\\/]node_modules[\\/]/,
        loader: 'builtin:swc-loader',
        options: {
          jsc: {
            parser: {
              syntax: 'ecmascript',
              jsx: true,
            },
          },
        },
      },
    ],
  },
};

要转换 .tsx 文件

module.exports = {
  module: {
    rules: [
      {
        test: /\.tsx$/,
        exclude: /[\\/]node_modules[\\/]/,
        loader: 'builtin:swc-loader',
        options: {
          jsc: {
            parser: {
              syntax: 'typescript',
              tsx: true,
            },
          },
        },
      },
    ],
  },
};

要转换 .ts 文件

module.exports = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /[\\/]node_modules[\\/]/,
        loader: 'builtin:swc-loader',
        options: {
          jsc: {
            parser: {
              syntax: 'typescript',
            },
          },
        },
      },
    ],
  },
};

target 不再影响用户代码

Rspack 将target 与 webpack 对齐。Rspack 现在不再转换任意用户代码,而是让加载器控制用户代码的转换。要将用户代码转换为目标环境需要的代码,请在 builtin:swc-loader 中添加 env

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /[\\/]node_modules[\\/]/,
        loader: "builtin:swc-loader",
        options: {
          jsc: {
            parser: {
              syntax: "ecmascript"
            }
          },
+         env: {
+           targets: "Chrome >= 48"
+         }
        }
      }
    ]
  }
}

删除扩展的解析扩展名

resolve.extensions 帮助我们在解析期间省略某些文件扩展名。在以前的版本中,支持 .ts.tsx.jsx,这些扩展名在最新版本中已被删除,这与 webpack 的行为一致。

为了获得相同行为,请将 resolve.extensions 更改为以下内容

module.exports = {
  resolve: {
    extensions: ['...', '.tsx', '.ts', '.jsx'], // "..." means to extend from the default extensions
  },
};

将 @swc/helpers 和 react-refresh 设为 peerDependencies

在我们删除默认转换之前,可以通过 target 将代码降级为 es5,并通过 builtin.react.refresh 将 react 刷新辅助代码插入到 react 组件中,因此我们将 @swc/helpersreact-refresh 安装为 @rspack/core 的依赖项,以提供开箱即用的体验。但由于我们现在删除了默认转换,并推荐使用 Rsbuild 来获得开箱即用的体验,因此 @swc/helpersreact-refresh 不再需要由 @rspack/core 安装,我们将它们设为 @rspack/core 的 peerDependencies。

如果您在使用 builtin:swc-loaderswc-loader 时使用 externalHelpers: true,现在您需要将 @swc/helpers 安装为项目依赖项。如果您使用的是 @rspack/plugin-react-refresh,现在您需要将 react-refresh 安装为项目的 devDependencies。

删除已弃用的内置选项

自 v0.4.0 以来,一些内置选项已被弃用。

如果您仍然使用 builtins.noEmitAssetsbuiltins.devFriendlySplitChunksbuiltins.reactbuiltins.htmlbuiltins.copybuiltins.minifyOptions,请查看将内置选项迁移到内置插件 以进行迁移。

如果您仍然使用 builtins.presetEnvbuiltins.decoratorbuiltins.pluginImportbuiltins.emotionbuiltins.relay,请查看迁移指南此处

删除 builtin:sass-loader

builtin:sass-loader 自 v0.4.0 以来已被弃用。它在 v0.5.0 中已被删除。如果您仍然使用它,请迁移到 sass-loader

删除 experiments.incrementalRebuild 选项

experiments.incrementalRebuild 选项自 v0.4.0 以来已被弃用。它在 v0.5.0 中已被删除。

删除 builtins.devFriendlySplitChunks 和 experiments.newSplitChunks

experiments.newSplitChunksbuiltins.devFriendlySplitChunks 自 v0.4.0 以来已被弃用。它在 v0.5.0 中已被删除。

删除 experiments.rspackFuture.newResolver 选项

experiments.rspackFuture.newResolver 自 v0.4.0 以来已被弃用。它在 v0.5.0 中已被删除。

弃用延迟应用入口

延迟应用入口被 rspackFuture 弃用:experiments.rspackFuture.disableApplyEntryLazily,它是在 v0.4.5 中引入的,在 v0.5.0 中默认启用,并且将在 v0.6.0 中删除。

experiments.rspackFuture.disableApplyEntryLazilyfalse 时,options.entry 仍然可以在调用 rspack(options) 后进行有效更改,但 true 时则不能,它的行为与 webpack5 相同。

此配置在大多数情况下对使用 Rspack 开发应用程序的用户没有影响,但应由 Rspack 插件或更高级框架的开发人员注意。

迁移指南

v0.5.0 删除了许多已弃用的功能,除此之外,v0.5.0 引入了四个重大变更,如果您正在使用 Rspack 开发应用程序,您只需要注意其中的两个。因此,如果您已经迁移到 v0.4+ 并且没有弃用警告,那么 v0.5.0 很容易迁移,如果您还没有迁移,请查看v0.4.0 迁移指南

添加 resolve.extensions

这是一个最有可能影响您的重大变更。

在您将 @rspack/core 升级到 v0.5.0 之后,如果您在构建时遇到错误:无法解析 './src/foo.tsx'无法解析 './src/foo.ts'无法解析 './src/foo.jsx',您需要在配置中添加 resolve.extensions = ['...', '.tsx', '.ts', '.jsx']

const configuration = {
  // ...
  resolve: {
+   extensions: ['...', '.tsx', '.ts', '.jsx'],
  },
}

您只需要将必要的扩展名添加到 resolve.extensions 中。例如,如果您没有使用任何 .tsx.ts 文件,只使用 .js.jsx 文件,那么您只需要将 '.jsx' 添加到 resolve.extensions 中。'.js' 是默认扩展名之一,所有默认扩展名(['.js', '.json', '.wasm'])由 '...' 表示。

安装 @swc/helpers 或 react-refresh

这是一个最有可能影响您的重大变更。

在您将 @rspack/core 升级到 v0.5.0 之后,如果您在构建时遇到错误:无法解析 @swc/helpers/some-helper无法解析 react-refresh/some-module,您需要在项目中安装 @swc/helpersreact-refresh

如果您在使用 builtin:swc-loaderswc-loader 时使用 externalHelpers: true,现在您需要将 @swc/helpers 安装为项目的依赖项。

npm
yarn
pnpm
bun
npm install @swc/helpers

如果您使用的是 @rspack/plugin-react-refresh,现在您需要将 react-refresh 安装为项目的 devDependencies。

npm
yarn
pnpm
bun
npm install react-refresh

应用 rspack.HotModuleReplacementPlugin

如果您使用的是 @rspack/cli 或 rsbuild 或 Rspack 的其他更高级框架来开发应用程序,您无需担心此问题。更高级框架或 cli 应该能够很好地处理这个问题。但如果您使用的是 @rspack/core 以及自定义开发服务器(不是 @rspack/dev-serverwebpack-dev-server),或者您正在开发自定义开发服务器,您需要注意这一点。

在 Rspack 中启用 HMR 之前是将 devServer.hot 设置为 true,但现在您需要在自定义开发服务器中自行应用 HotModuleReplacementPlugin

class CustomDevServer {
  // ...
  enableHMR(compiler) {
-   compiler.options.devServer ??= {};
-   compiler.options.devServer.hot = true;
+   new compiler.webpack.HotModuleReplacementPlugin().apply(compiler);
  }
}

不要在 rspack(options) 之后更改入口选项

如果您使用的是 @rspack/cli,或 rsbuild,或 Rspack 的其他更高级别的框架来开发应用程序,您无需担心这一点。这应该由更高级别的框架或 cli 很好地处理。但是,如果您正在开发插件或更高级别的框架,则需要注意这一点。

在预先添加 Rspack 中的额外入口之前,它是将其预先添加到 compiler.options.entry 中,但现在您需要自己应用 EntryPlugin

const rspack = require('@rspack/core');
const compiler = rspack(options);

function prependEntry(compiler, additionalEntry) {
-  for (const key in compiler.options.entry) {
-    compiler.options.entry[key].import = [
-      additionalEntry,
-      ...(compiler.options.entry[key].import || []),
-    ];
-  }
+  new compiler.webpack.EntryPlugin(compiler.context, additionalEntry, {
+    name: undefined, // `name: undefined` to prepend the it to every entry, or add it to a specified entry with specified entry name
+  }).apply(compiler);
}

prependEntry(compiler, 'dev-client.js');