webpack迁移rsbuild——配置深度对比

综合对比

webpack项目整体上可以无痛迁移到rsbuild,其中rspack对标webpack,swc对标babel和terser,这些对标不仅是从能力上对标,更是参考了目标的大量配置api设计,因此绝大多数重要能力的配置api都可以沿用webpack的,迁移过程中几乎不需要关注能力/特性丢失问题,体验极佳。

编译

js(x)/ts(x)编译

webapck大多基于babel,rsbuild基于swc,swc的配置也对标了babel常用的preset和plugin,如@babel/preset-react,不过也缺失了一些细节优化插件,如@babel/plugin-proposal-class-properties。

rsbuild提供了常用的配置插件,默认值的设置也比较贴近实践,使用更为简单,比如对react的编译:

javascript 复制代码
import { pluginReact } from '@rsbuild/plugin-react';

export default {
  plugins: [pluginReact()],
};

如果确实需要使用部分babel插件,比如项目中可能有自定义的ast处理脚本,rsbuild也提供了接入方式:

javascript 复制代码
import { pluginBabel } from '@rsbuild/plugin-babel';

export default {
  plugins: [pluginBabel()],
};

需要注意的是,该插件并不是将swc切换为babel,而是在swc的基础上额外执行babel转义,因此会增加编译时间。

ts装饰器

Rsbuild 不会读取 tsconfig.json 中的 experimentalDecorators 选项,而是提供了 decorators.version 配置项来指定装饰器版本

css 复制代码
export default {
    source: { 
        decorators: { 
            version: 'legacy', 
        }, 
    }, 
};

另外swc明确支持ts的decoratorMetadata,迁移的时候可以不用担心装饰器被破坏。

样式

less/sass

webpack的less-loader,sass-loader对应@rsbuild/plugin-less和@rsbuild/plugin-sass,配置的不同点在于webpack通过module.rules[].test匹配,而rsbuild通过插件本身的include和exclude

css modules

不管是规范还是多数实践,项目中一般都会对css module文件名中增加module标记,比如*.module.less。rsbuild也是根据该规范判断样式文件是否启用css modules。但webpack更灵活,可以任意设置该文件是否启用css modules:

javascript 复制代码
 {
        test: /\.module\.css$/,
        use: [
          'style-loader', // 或 mini-css-extract-plugin.loader
          {
            loader: 'css-loader',
            options: {
              modules: {
                mode: 'local', // 局部作用域(默认)
                localIdentName: '[name]__[local]--[hash:base64:5]', // 类名生成规则
                exportLocalsConvention: 'camelCase', // 导出驼峰命名(如 .btn-primary → btnPrimary)
              },
            },
          },
        ],
      },

因此如果迁移rsbuild,建议对不符合css modules命名规范的文件重新命名。 当然rsbuild也可以对任意文件设置是否启用css modules 在默认情况下,只有 *.module.css 结尾的文件才被视为 CSS Modules 模块。

如果你想将其他 CSS 文件也当做 CSS Modules 模块进行处理,可以通过配置 output.cssModules.auto 来实现。

比如:

javascript 复制代码
export default {
  output: {
    cssModules: {
      auto: (resource) => {
        return resource.includes('.module.') || resource.includes('shared/');
      },
    },
  },
};

设置后,以下两个文件都会被视为 CSS Modules:

javascript 复制代码
import styles1 from './foo.module.css';
import styles2 from './shared/bar.css';

但个人并不推荐该方式。

postcss和tailwind

rsbuild的tools.postcss对标webpack的postcss-loader,对tailwind的配置也通过postcss。不过其内置的Lightning CSS覆盖了postcss一些插件,比如autoprefixer。

压缩

SWC vs Terser

SWC的压缩配置对标Terser,Terser有的SWC几乎都有,可以无脑切换。

css-minimizer-webpack-plugin和Lightning CSS的压缩

css-minimizer-webpack-plugin可以设置压缩工具为cssnano(默认)、Lightning CSS、csso,rsbuild仅支持Lightning CSS(当前主流)。Lightning CSS相当于cssnano(压缩)+ autoprefixer(前缀)+ postcss-preset-env(语法降级)

其他重要插件

svgr

webpack rsbuild 重要区别
插件 @svgr/webpack @rsbuild/plugin-svgr 混合导入

webpack支持混合导入,svg可以当成path或一个React组件

javascript 复制代码
import starUrl, { ReactComponent as Star } from './star.svg'


const App = () => (
  <div>
    <img src={starUrl} alt="star" />
    <Star />
  </div>
)

@rsbuild/plugin-svgr开启具名导入后,需要额外开启混合导入,否则无法当成path处理。虽然该插件支持混合导入,但推荐的写法如下

javascript 复制代码
import Logo from './logo.svg?react'; 
export const App = () => <Logo />;

建议优先使用 ?react 来将 SVG 转换为 React 组件,而不是使用混合导入。因为混合导入有如下局限性:

  1. 包体积增加:混合导入会导致单个 SVG 模块被编译为两种代码(即使部分导出没有被使用),这会增加产物的包体积。
  2. 编译速度下降:混合导入会产生额外的编译开销。即使代码中未使用到 ReactComponent 导出,SVG 文件仍然会被 SVGR 编译。而 SVGR 是基于 Babel 实现的,性能开销较大。

code-inspector-plugin

webpack rsbuild 重要区别
插件 code-inspector-plugin code-inspector-plugin 配置方式

webpack和rspack的配置方式类似

javascript 复制代码
// webpack.config.js
const { codeInspectorPlugin } = require('code-inspector-plugin');

module.exports = () => ({
  plugins: [
    codeInspectorPlugin({
      bundler: 'webpack',
    }),
  ],
});
// rspack.config.js
const { codeInspectorPlugin } = require('code-inspector-plugin');

module.exports = {
  // other config...
  plugins: [
    codeInspectorPlugin({
      bundler: 'rspack',
    }),
    // other plugins...
  ],
};

但rsbuild的配置略有不同------rsbuild的plugin并不是rspack的plugin

javascript 复制代码
// rsbuild.config.js
import { defineConfig } from '@rsbuild/core';
import { codeInspectorPlugin } from 'code-inspector-plugin';

export default defineConfig({
  // ...other config
  tools: {
    rspack: {
      plugins: [
        codeInspectorPlugin({
          bundler: 'rspack',
        }),
      ],
    },
  },
});

rsbuild vs vite 重要特性横向对比

按需编译

vite的按需编译依赖浏览器的esm加载机制,而rsbuild的按需编译(Lazy compilation),依赖于拆包,即只编译入口,动态import引入文件按需编译。如果问开发服务器启动时间,那肯定是vite更快,但要问开发环境页面加载时间,大型项目可能rsbuild更快。

热更新

rsbuild的热更新还是chunk粒度,而vite是文件粒度,速度上来说vite更快,但实际体验差距不大。

兼容性

如果都是从webpack升级,相比vite,显然rsbuild更安全,除了插件的兼容,更关键的是编译兼容。

swc的语法降级,对标babel的@babel/preset-env,支持按需引入polyfill(类似useBuiltIns: 'usage');同时swc也可以安全地编译ts的元数据和装饰器;压缩上对标Terser,几乎可以无缝迁移相关配置。这三点超越了esbuild。

webpack特性丢失问题

rsbuild几乎没有特性丢失的问题,比如模块联邦,splitChuks均能与webpack保持一致,而vite由于内置打包是rollup,这两个特性支持并不好。

结论

纯个人意见,充满主观判断:rsbuild相比webpack全面超越,相比vite,无论是兼容性还是开发/配置体验都更好。

相关推荐
前端小黑屋2 小时前
查看项目中无引用到的文件、函数
前端
前端小黑屋2 小时前
小程序直播挂件Pendant问题
前端·微信小程序·直播
俊男无期2 小时前
超效率工作法
java·前端·数据库
LYFlied2 小时前
【每日算法】LeetCode 46. 全排列
前端·算法·leetcode·面试·职场和发展
刘一说2 小时前
Vue Router:官方路由解决方案解析
前端·javascript·vue.js
wgego2 小时前
Polar靶场web 随记
前端
DEMO派2 小时前
深拷贝 structuredClone 与 JSON 方法作用及比较
前端
DEMO派2 小时前
JavaScript性能优化由浅入深
前端
前端小黑屋2 小时前
企微接口h5调用问题记录
前端