跳到主要内容

Rspack 核心知识

一、 Rspack 是什么?

Rspack 是一个基于 Rust 开发的高性能 Web 构建工具,由 Webpack 团队成员参与(ByteDance Web Infra 团队主导)。它的核心目标是提供 极高的构建性能,同时 尽可能地与 Webpack 生态兼容,旨在显著降低 Webpack 项目的编译和热更新时间。

核心出发点:

  1. 性能瓶颈: 传统基于 JavaScript 的构建工具(如 Webpack)受限于 Node.js 的单线程特性以及 JavaScript 本身的执行效率,在大型项目中,构建和热更新(HMR)速度可能成为开发瓶颈。
  2. 利用 Rust 优势: Rust 是一门以性能、安全和并发性著称的系统编程语言。通过 Rust 重写构建工具的核心逻辑,可以充分利用多核 CPU 进行并行计算,并减少 JavaScript 解释执行带来的开销。
  3. Webpack 兼容性: Webpack 拥有庞大且成熟的生态系统(Loaders, Plugins)。Rspack 的目标是尽可能复用这套生态,降低现有 Webpack 项目的迁移成本。它旨在兼容 Webpack 的核心配置项、Loader API 和 Plugin API。

二、 Rspack 的核心概念与 Webpack 的异同

由于 Rspack 旨在兼容 Webpack,因此它沿用了许多 Webpack 的核心概念。理解这些概念是掌握 Rspack 的基础。

  1. Entry (入口)

    • 说明: 与 Webpack 相同,指定构建的起点。Rspack 从入口文件开始分析依赖关系图。可以配置单个或多个入口。

    • 配置: 与 Webpack 语法基本一致。

    • 示例 (rspack.config.js):

      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      entry: "./src/index.js", // 单入口
      // 或 多入口对象语法
      // entry: {
      // main: './src/main.js',
      // admin: './src/admin.js',
      // },
      // 或 多入口依赖语法 (表示 app 依赖 shared)
      // entry: {
      // app: { import: './src/app.js', dependOn: 'shared' },
      // shared: './src/shared.js'
      // },
      };
      module.exports = config;
      // src/index.js
      import { log } from "./utils";
      import "./style.css";

      log("Hello from Rspack!");
  2. Output (输出)

    • 说明: 与 Webpack 相同,配置构建产物的存放位置和命名规则。

    • 配置: 与 Webpack 语法基本一致。

    • 示例 (rspack.config.js):

      // rspack.config.js
      const path = require("path");

      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      entry: "./src/index.js",
      output: {
      path: path.resolve(__dirname, "dist"), // 输出目录
      filename: "bundle.js", // 单入口输出文件名
      // 多入口时使用占位符:
      // filename: '[name].[contenthash].js',
      publicPath: "/", // 资源公共路径
      assetModuleFilename: "assets/[hash][ext][query]", // 资源模块文件名 (类似 Webpack 5)
      clean: true, // 构建前清理输出目录 (内置)
      },
      };
      module.exports = config;
  3. Mode (模式)

    • 说明: 与 Webpack 相同,分为 developmentproduction。Rspack 会根据模式启用不同的内置优化和默认配置。
    • 配置: 通过配置文件或 CLI 参数设置。
    • 示例 (rspack.config.js):
      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      mode: "production", // 或 'development'
      // ...
      };
      module.exports = config;
      # 通过 CLI 设置
      npx rspack build --mode production
      npx rspack serve --mode development
  4. Loaders (加载器) - (重要区别点)

    • 说明: Rspack 的核心优势之一在于其 内置了许多常用的 Loader 功能,这些功能由 Rust 实现,性能远超对应的 JavaScript Loader。对于 Rspack 无法原生支持的转换,它也 兼容 Webpack 的 Loader API,允许你使用现有的 Webpack Loader。

    • Rspack 内置 Loaders (通过 module.rules.type): Rspack 使用 type 字段来指定由 Rust 处理的内置转换类型,取代了 Webpack 中需要安装和配置多个 Loader 的繁琐步骤。

      • 'javascript/auto': 默认,处理 JS/TS/JSX/TSX (使用内置的 SWC)。
      • 'css': 处理纯 CSS 文件,支持 @importurl()
      • 'css/module': 处理 CSS Modules。
      • 'asset/resource': 发送单独的文件并导出 URL (类似 file-loader)。
      • 'asset/inline': 导出资源的 data URI (类似 url-loader data URL)。
      • 'asset/source': 导出资源的源代码 (类似 raw-loader)。
      • 'asset': 自动在 asset/resourceasset/inline 之间选择 (基于 parser.dataUrlCondition)。
      • 'json': 加载 JSON 文件 (支持 Tree Shaking)。
      • 'web-worker': 处理 Web Worker。
    • 使用 Webpack JS Loaders: 通过 module.rules.use 数组配置,Rspack 使用 @rspack/loader-runner 来执行这些 JS Loader。

    • 配置示例:

      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ... entry, output, mode
      module: {
      rules: [
      // 使用内置 SWC 处理 JS/TS/JSX/TSX (通常无需配置,此为显式写法)
      {
      test: /\.[tj]sx?$/,
      // type: 'javascript/auto', // 默认就是这个类型
      // 如果需要自定义 SWC 配置
      use: {
      loader: "builtin:swc-loader",
      options: {
      // 参考 Rspack 文档配置 SWC
      jsc: {
      parser: {
      syntax: "typescript",
      tsx: true,
      },
      transform: {
      react: {
      runtime: "automatic", // React 17+ 新 JSX 转换
      },
      },
      },
      },
      },
      },
      // 使用内置 CSS Loader 处理 CSS Modules
      {
      test: /\.module\.css$/i,
      type: "css/module", // 内置 CSS Modules 处理
      // parser: { // 可选:配置 CSS Modules 选项
      // namedExports: true, // 使用命名导出
      // },
      },
      // 使用内置 CSS Loader 处理普通 CSS
      {
      test: /\.css$/i,
      exclude: /\.module\.css$/i, // 排除 CSS Modules
      type: "css", // 内置普通 CSS 处理
      },
      // 使用内置 Asset Modules 处理图片
      {
      test: /\.(png|svg|jpg|jpeg|gif)$/i,
      type: "asset/resource", // 相当于 file-loader
      },
      // 使用内置 Asset Modules 处理字体
      {
      test: /\.(woff|woff2|eot|ttf|otf)$/i,
      type: "asset/resource",
      },
      // 示例:如果必须使用特定的 Webpack Loader (如 postcss-loader)
      // 需要安装: npm install --save-dev postcss-loader autoprefixer postcss
      // {
      // test: /\.css$/i,
      // use: [
      // 'style-loader', // Rspack 暂未内置 style-loader 功能,仍需使用 JS loader
      // 'css-loader', // 可选,如果需要 CSS Modules 或特定的 css-loader 选项
      // {
      // loader: 'postcss-loader',
      // options: {
      // postcssOptions: {
      // plugins: [
      // 'autoprefixer',
      // ],
      // },
      // },
      // },
      // ],
      // // 注意:当使用 use 时,不能再指定 type
      // },
      // 示例:使用 Sass (需要安装 sass-loader 和 sass)
      // npm install --save-dev sass-loader sass
      {
      test: /\.s[ac]ss$/i,
      use: [
      "style-loader", // 仍需 JS Loader
      "css-loader", // 可选
      "sass-loader", // 使用 JS sass-loader
      ],
      // Rspack 也在努力内置 Sass/Less 处理
      // type: 'css/auto', // 或期待未来的内置类型
      },
      ],
      },
      // 配置内置 SWC 如何处理 CSS (将 css/module 和 css 类型应用到匹配的文件)
      // 这是另一种配置内置 CSS 处理的方式,与 rules 中的 type 效果类似
      // builtins: {
      // css: {
      // modules: {
      // localsConvention: 'camelCase', // 配置 CSS Modules 行为
      // }
      // }
      // }
      };
      module.exports = config;
      /* src/style.css */
      body {
      background-color: lightcoral;
      font-family: sans-serif;
      }
      /* src/vars.module.css */
      .primaryColor {
      color: blue;
      }
      // src/utils.js
      import styles from "./vars.module.css"; // 导入 CSS Module

      export const log = (message) => {
      console.log(`[RSPACK LOG] ${message}`);
      console.log("Primary color from CSS Module:", styles.primaryColor); // 使用驼峰式 primaryColor
      // TS/JSX 示例 (假设入口是 .tsx)
      // const element = <div className={styles.primaryColor}>Hello JSX!</div>;
      // console.log(element);
      };
  5. Plugins (插件) - (重要区别点)

    • 说明: 与 Loader 类似,Rspack 内置了许多常用且性能关键的 Webpack 插件功能,由 Rust 实现。同时,它也 兼容 Webpack 的 Plugin API,允许开发者使用现有的 Webpack 插件。

    • Rspack 内置 Plugins (通过 builtins 配置项或直接引入):

      • HtmlRspackPlugin: 对应 html-webpack-plugin,用于生成 HTML 文件并注入打包后的资源。
      • DefinePlugin: 对应 webpack.DefinePlugin,用于定义全局常量。
      • ProvidePlugin: 对应 webpack.ProvidePlugin,自动加载模块。
      • CopyRspackPlugin: 对应 copy-webpack-plugin,用于复制文件或目录。
      • HotModuleReplacementPlugin: 内置 HMR 支持,通常无需手动添加。
      • 内置压缩 (Terser / SWC Minifier): 在 mode: 'production' 时默认启用 JS 压缩。
      • 内置 CSS 压缩 (Lightning CSS): 在 mode: 'production' 时默认启用 CSS 压缩。
      • ... 更多内置插件正在不断增加。
    • 使用 Webpack JS Plugins: 可以像在 Webpack 中一样 requirenew Webpack 插件。Rspack 会尝试兼容其钩子 (hooks)。

    • 配置示例:

      // rspack.config.js
      const rspack = require("@rspack/core");
      const path = require("path");
      // const CopyPlugin = require('copy-webpack-plugin'); // 示例:使用 Webpack 的 CopyPlugin

      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ... entry, output, mode, module
      plugins: [
      // 使用内置的 HtmlRspackPlugin
      new rspack.HtmlRspackPlugin({
      template: "./public/index.html", // 指定 HTML 模板
      title: "My Rspack App", // 传递给模板的变量
      // favicon: './public/favicon.ico' // 指定 favicon
      }),
      // 使用内置的 DefinePlugin
      new rspack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify(
      process.env.NODE_ENV || "development"
      ),
      __API_ENDPOINT__: JSON.stringify("https://api.example.com"),
      }),
      // 使用内置的 CopyPlugin (如果已内置,推荐使用内置版本)
      new rspack.CopyRspackPlugin({
      patterns: [
      { from: "public/assets", to: "static" }, // 复制 public/assets 到 dist/static
      ],
      }),
      // 示例:如果需要使用 Webpack 的插件 (假设 Rspack 尚未内置或需要特定功能)
      // new CopyPlugin({
      // patterns: [
      // { from: "other_assets", to: "other_static" },
      // ],
      // }),
      ],
      // 也可以通过 builtins 字段配置一些内置插件的行为
      // builtins: {
      // html: [{ // 配置 HtmlRspackPlugin
      // template: './public/index.html',
      // }],
      // define: { // 配置 DefinePlugin
      // 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      // },
      // copy: { // 配置 CopyRspackPlugin
      // patterns: [{ from: 'public/assets', to: 'static' }],
      // }
      // }
      };
      module.exports = config;
      <!-- public/index.html -->
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="utf-8" />
      <!-- 使用 HtmlRspackPlugin 传递的 title -->
      <title><%= html.title %></title>
      <!-- favicon link 会自动处理 -->
      </head>
      <body>
      <div id="root"></div>
      <!-- 打包后的 JS/CSS 会被自动注入 -->
      </body>
      </html>
  6. Dev Server & HMR (开发服务器与热模块替换)

    • 说明: Rspack 提供了 @rspack/dev-server 包,功能类似于 webpack-dev-server,但其 HMR 功能由 Rust 实现,响应速度通常更快。
    • 配置:rspack.config.js 中配置 devServer 对象。
    • 示例 (rspack.config.js):
      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ... entry, output, mode, module, plugins
      devServer: {
      port: 8080, // 指定端口
      open: true, // 自动打开浏览器
      hot: true, // 启用 HMR (通常默认启用)
      // static: { // 提供静态文件目录 (可选)
      // directory: path.join(__dirname, 'public'),
      // },
      historyApiFallback: true, // 支持 SPA 路由 (如 React Router)
      // proxy: { // 配置 API 代理 (与 Webpack 类似)
      // '/api': {
      // target: 'http://localhost:3000',
      // pathRewrite: { '^/api': '' },
      // changeOrigin: true,
      // },
      // },
      },
      };
      module.exports = config;
      // package.json scripts
      "scripts": {
      "dev": "rspack serve", // 启动开发服务器
      "build": "rspack build" // 执行生产构建
      }
  7. Target (编译目标)

    • 说明: 与 Webpack 相同,指定代码的运行环境 (如 web, node, webworker)。Rspack 会根据 target 调整构建策略。
    • 配置:
      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      target: "web", // 默认值,适用于浏览器环境
      // target: ['web', 'es2020'], // 可以指定 ECMAScript 版本
      // target: 'node', // 适用于 Node.js 环境
      };
      module.exports = config;
  8. Resolve (模块解析)

    • 说明: 与 Webpack 相同,配置模块如何被解析,例如设置别名 (alias)、自动解析的文件扩展名 (extensions) 等。

    • 配置:

      // rspack.config.js
      const path = require("path");

      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ...
      resolve: {
      extensions: [".js", ".jsx", ".ts", ".tsx", ".json"], // 自动解析这些扩展名
      alias: {
      // 设置路径别名
      "@": path.resolve(__dirname, "src/"),
      components: path.resolve(__dirname, "src/components/"),
      },
      // modules: ['node_modules', path.resolve(__dirname, 'my_modules')], // 查找模块的目录
      // fallback: { // Polyfill Node.js核心模块 (在浏览器环境)
      // "crypto": require.resolve("crypto-browserify"),
      // "stream": require.resolve("stream-browserify"),
      // }
      },
      };
      module.exports = config;
      // src/some_component.js
      import utils from "@/utils"; // 使用了 '@' 别名
      import Button from "components/Button"; // 使用了 'components' 别名
  9. Optimization (优化)

    • 说明: Rspack 内置了多种基于 Rust 的优化策略,在 production 模式下默认启用。
      • Minification (压缩): 默认使用 SWC Minifier (也可配置为 Terser) 压缩 JS,使用 Lightning CSS 压缩 CSS。性能通常优于 JS 实现的压缩器。
      • Tree Shaking: 内置支持,移除未使用的代码。
      • Code Splitting (代码分割): 支持 splitChunks 配置,策略与 Webpack 类似。
      • Scope Hoisting (作用域提升): 内置支持,减少闭包,提升运行时性能。
    • 配置: 通过 optimization 对象进行配置,语法与 Webpack 类似。
      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ...
      mode: "production", // 优化主要在生产模式下生效
      optimization: {
      minimize: true, // 显式启用压缩 (生产模式下默认为 true)
      // minimizer: [ // 自定义压缩器 (需要安装 @rspack/plugin-terser)
      // new rspack.TerserPlugin({ /* Terser options */ }),
      // new rspack.LightningCssMinimizerRspackPlugin({ /* Lightning CSS options */ })
      // ],
      splitChunks: {
      // 配置代码分割
      chunks: "all", // 对所有类型的 chunk 进行分割
      cacheGroups: {
      // 自定义分割组
      vendor: {
      test: /[\\/]node_modules[\\/]/,
      name: "vendors",
      chunks: "all",
      priority: -10, // 优先级
      },
      react: {
      // 单独打包 react 相关库
      test: /[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/,
      name: "react-vendors",
      chunks: "all",
      priority: 0, // 更高优先级
      },
      },
      },
      runtimeChunk: "single", // 将运行时代码提取到单独的文件
      // sideEffects: true, // 告知 Rspack package.json 中的 "sideEffects" 属性是有效的 (用于 Tree Shaking)
      },
      // 可以在 package.json 中配置 sideEffects 来辅助 Tree Shaking
      // package.json
      // {
      // "name": "my-app",
      // "version": "1.0.0",
      // "sideEffects": false, // 表示所有文件都没有副作用,可以大胆 Tree Shaking
      // // 或指定有副作用的文件/目录
      // // "sideEffects": ["./src/styles/global.css", "*.css"]
      // }
      };
      module.exports = config;
  10. Devtool (Source Map)

    • 说明: 与 Webpack 相同,控制如何生成 Source Map 以方便调试。Rspack 支持多种 Source Map 格式。
    • 配置:
      // rspack.config.js
      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ...
      // 开发环境推荐:构建速度快,信息较全
      devtool:
      process.env.NODE_ENV === "production"
      ? "source-map"
      : "eval-cheap-module-source-map",
      // 生产环境推荐:'source-map' (信息最全,但较慢,生成单独文件) 或 'hidden-source-map' (用于错误报告) 或 false
      };
      module.exports = config;
  11. Builtins (内置能力配置)

    • 说明: Rspack 提供了一个 builtins 配置项,用于集中配置其内置的 Loader 和 Plugin 的行为,有时可以替代 module.rulesplugins 中的部分配置。

    • 配置示例:

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

      /** @type {import('@rspack/cli').Configuration} */
      const config = {
      // ...
      builtins: {
      // 配置内置的 SWC Loader (效果类似 module.rules 中配置 builtin:swc-loader)
      // swcLoader: {
      // jsc: { /* ... SWC jsc config ... */ },
      // env: { /* ... SWC env config ... */ }
      // },

      // 配置内置的 CSS 处理 (效果类似 module.rules 中配置 type: 'css'/'css/module')
      css: {
      modules: {
      // 配置 CSS Modules
      localsConvention: "camelCaseOnly", // 仅使用驼峰命名导出
      // localIdentName: '[path][name]__[local]--[hash:base64:5]', // 自定义类名格式
      },
      },

      // 配置内置的 HtmlRspackPlugin (效果同 plugins 数组中 new rspack.HtmlRspackPlugin)
      html: [
      {
      template: "./public/index.html",
      title: "Rspack App via Builtins",
      },
      ],

      // 配置内置的 DefinePlugin
      define: {
      "process.env.BUILTIN_VAR": JSON.stringify(
      "value from builtins.define"
      ),
      },

      // 配置内置的 CopyPlugin
      // copy: {
      // patterns: [ { from: 'public' } ]
      // },

      // 配置 React Fast Refresh (通常在开发模式下自动启用,无需手动配置)
      // react: {
      // runtime: 'automatic',
      // refresh: process.env.NODE_ENV === 'development'
      // }

      // 配置 Tree Shaking (通常无需手动配置)
      // treeShaking: true, // 'module'
      },
      };
      module.exports = config;

三、 Rspack 的关键特性与优势

  1. 极致性能:

    • 基于 Rust 编写,充分利用多核并行处理和系统级语言优势。
    • 内置高性能的 Rust 实现的 Loaders 和 Plugins (如 SWC 用于 JS/TS 转换和压缩,Lightning CSS 用于 CSS 处理)。
    • 增量编译和持久化缓存机制进一步加速二次构建。
    • 开发模式下的 HMR 速度极快。
  2. Webpack 兼容性:

    • 支持大部分 Webpack 核心配置选项。
    • 兼容 Webpack Loader API,可以使用现有的 JS Loader。
    • 兼容 Webpack Plugin API,可以使用现有的 JS Plugin。
    • 使得从现有 Webpack 项目迁移到 Rspack 的成本相对较低。
  3. 开箱即用 (Built-in First):

    • 内置了对 TypeScript, JSX, CSS, CSS Modules, Sass/Less (逐步完善中), 静态资源等的原生支持,通常无需安装和配置额外的 Loader。
    • 内置了常用的插件功能,如 HTML 生成、代码压缩、HMR 等。
    • 简化了配置,降低了新项目的上手门槛。
  4. 优秀的开发体验:

    • 极快的冷启动和热更新速度,提升开发效率。
    • 清晰的错误提示和调试信息。
    • 积极迭代,社区活跃。

四、 如何开始使用 Rspack

  1. 安装依赖:

    npm install @rspack/cli @rspack/core --save-dev
    # 或使用 yarn / pnpm
    # yarn add @rspack/cli @rspack/core --dev
    # pnpm add -D @rspack/cli @rspack/core
  2. 创建配置文件 (rspack.config.js):

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

    /** @type {import('@rspack/cli').Configuration} */
    const config = {
    context: __dirname, // 基础目录,绝对路径,用于从配置中解析入口点和加载器
    entry: {
    main: "./src/index.js",
    },
    output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "dist"),
    clean: true,
    },
    module: {
    rules: [
    // Rspack 默认会处理 JS/TS/JSX/TSX
    {
    test: /\.css$/i,
    type: "css/auto", // 自动处理普通 CSS 和 CSS Modules
    },
    {
    test: /\.(png|svg|jpg|gif)$/i,
    type: "asset/resource",
    },
    ],
    },
    plugins: [
    new rspack.HtmlRspackPlugin({
    template: "./public/index.html",
    }),
    ],
    devServer: {
    port: 3000,
    open: true,
    hot: true,
    },
    mode: process.env.NODE_ENV || "development",
    // devtool: 'source-map' // 可选:生成 source map
    };
    module.exports = config;
  3. 准备入口文件和模板:

    • src/index.js
    • src/style.css
    • public/index.html
  4. 添加 package.json 脚本:

    {
    "name": "my-rspack-project",
    "version": "1.0.0",
    "scripts": {
    "dev": "rspack serve --config rspack.config.js",
    "build": "NODE_ENV=production rspack build --config rspack.config.js"
    },
    "devDependencies": {
    "@rspack/cli": "^X.X.X", // 使用最新版本
    "@rspack/core": "^X.X.X"
    }
    }
  5. 运行命令:

    npm run dev   # 启动开发服务器
    npm run build # 执行生产构建

五、 注意事项与 Rspack 的当前状态

  • 仍在快速发展中: Rspack 是一个相对较新的项目,API 和功能仍在不断迭代和完善中。虽然核心功能稳定,但某些边缘场景或特定的 Webpack Loader/Plugin 兼容性可能还在优化。
  • 优先使用内置能力: 为了获得最佳性能,应优先利用 Rspack 的内置 Loader (type) 和内置 Plugin (builtinsrspack.*Plugin)。仅在内置能力无法满足需求或需要特定 Webpack 生态功能时,才考虑使用 JS Loader/Plugin。
  • 文档和社区: 官方文档是学习 Rspack 的最佳资源。社区也在不断壮大,可以找到很多实践案例和问题解决方案。
  • 兼容性层开销: 使用 Webpack JS Loader/Plugin 会引入 @rspack/loader-runner 或兼容层,这会带来一定的性能开销,虽然 Rspack 尽力优化,但通常不如纯 Rust 实现快。
  • 生态差异: 尽管兼容 Webpack,但并非所有 Webpack Loader/Plugin 都能 100% 无缝工作,特别是那些深度依赖 Webpack 内部机制或使用了非标准 API 的插件。