配置 Rspack

Rsbuild 支持直接修改 Rspack 配置对象,也支持通过 rspack-chain 来修改 Rsbuild 内置的 Rspack 配置。

TIP

Rsbuild 内置的 Rspack 配置会随着迭代而发生变化,这些变化不会反映在 semver 中,因此在升级 Rsbuild 时,你的自定义配置可能会失效。

查看 Rspack 配置

Rsbuild 提供了 rsbuild inspect 命令来查看 Rsbuild 最终生成的 Rspack 配置。

你也可以通过 调试模式 来查看。

修改配置对象

你可以使用 Rsbuild 的 tools.rspack 选项来修改 Rspack 配置对象。

比如注册 Rspack 插件或 webpack 插件:

rsbuild.config.ts
export default {
  tools: {
    rspack: {
      plugins: [SomeWebpackPlugin()],
    },
  },
};

比如以函数的形式修改 Rspack 配置:

rsbuild.config.ts
export default {
  tools: {
    rspack: (config, { env }) => {
      if (env === 'development') {
        config.devtool = 'cheap-module-eval-source-map';
      }
      return config;
    },
  },
};

请查看 tools.rspack 文档 来了解完整用法。

使用 Rspack Chain

rspack-chain 是一个用于配置 Rspack 的工具库。它提供了链式 API,使得配置 Rspack 变得更加灵活。通过使用 rspack-chain,你可以更方便地修改和扩展 Rspack 配置,而不需要直接操作复杂的配置对象。

tools.bundlerChain

Rsbuild 提供了 tools.bundlerChain 配置项来修改 rspack-chain。

tools.bundlerChain 的值是一个函数,接收两个参数:

  • 第一个参数为 rspack-chain 实例,你可以通过 它来修改默认的 Rspack 配置。
  • 第二个参数为一个工具对象,包括 envisProdCHAIN_ID 等。

下面是一个基本示例:

rsbuild.config.ts
export default {
  tools: {
    bundlerChain: (chain, { env }) => {
      if (env === 'development') {
        chain.devtool('cheap-module-eval-source-map');
      }
    },
  },
};

tools.bundlerChain 还可以是一个异步函数:

rsbuild.config.ts
export default {
  tools: {
    bundlerChain: (chain, { env }) => {
      const value = await fetchValue();
      chain.devtool(value);
    },
  },
};

背景知识

在开始使用 rspack-chain 来修改 Rspack 配置之前,请先了解一些背景知识。

关于 ID

简单来说,rspack-chain 要求使用者为每个 Rule、Loader、Plugin、Minimizer 都设置一个独一无二的 id,通过这个 id,就可以便捷地从嵌套层级很深的对象中找到所需的对象。

Rsbuild 将内部定义的全部 id 都通过 CHAIN_ID 对象导出,因此你可以通过这些导出的 id,快速定位到你想要修改的 Loader 或 Plugin,而不需要在 Rspack 配置对象里通过复杂的遍历寻找。

比如通过 CHAIN_ID.PLUGIN.HTML 来删除内置的 HTML 插件:

rsbuild.config.ts
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      //
      chain.plugins.delete(CHAIN_ID.PLUGIN.HTML);
    },
  },
};

ID 类型

CHAIN_ID 对象包含了多种 id,对应的含义如下:

CHAIN_ID 字段 对应的配置 描述
CHAIN_ID.PLUGIN plugins[i] 对应 Rspack 配置中的一个插件
CHAIN_ID.RULE module.rules[i] 对应 Rspack 配置中的一个 Rule
CHAIN_ID.USE module.rules[i].loader 对应 Rspack 配置中的一个 Loader
CHAIN_ID.MINIMIZER optimization.minimizer 对应 Rspack 配置中的一个压缩工具
CHAIN_ID.RESOLVE_PLUGIN resolve.plugins[i] 对应 Rspack 配置中的一个 Resolve 插件

示例

配置 loader

下面是新增、修改和删除 Rspack loader 的示例。

  • 新增一个 loader 来处理 .md 文件:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain) => {
      chain.module
        .rule('md')
        .test(/\.md$/)
        .use('md-loader')
        // loader 的包名或模块路径
        .loader('md-loader');
    },
  },
};
  • 修改内置的 SWC loader 选项:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      chain.module
        .rule(CHAIN_ID.RULE.JS)
        .use(CHAIN_ID.USE.SWC)
        .tap((options) => {
          console.log(options);
          return options;
        });
    },
  },
};
  • 删除内置的 SWC loader:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      chain.module.rule(CHAIN_ID.RULE.JS).uses.delete(CHAIN_ID.USE.SWC);
    },
  },
};
  • 在内置的 SWC loader 之后插入一个 loader,它会早于 SWC loader 执行:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      chain.module
        .rule(CHAIN_ID.RULE.JS)
        .use('my-loader')
        .after(CHAIN_ID.USE.SWC)
        // loader 的包名或模块路径
        .loader('my-loader')
        .options({
          // some options
        });
    },
  },
};

注意:Rspack 的 loader 是以相反顺序执行的。

  • 在内置的 SWC loader 之前插入一个 loader,它会晚于 SWC loader 执行:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      chain.module
        .rule(CHAIN_ID.RULE.JS)
        // loader id,没有实际意义,仅用于定位
        .use('my-loader')
        .before(CHAIN_ID.USE.SWC)
        // loader 的包名或模块路径
        .loader('my-loader')
        .options({
          // some options
        });
    },
  },
};
  • 删除内置的 CSS 处理规则:
rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { CHAIN_ID }) => {
      chain.module.rules.delete(CHAIN_ID.RULE.CSS);
    },
  },
};

配置 Plugin

下面是新增、修改和删除 Rspack 插件的示例。

rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { bundler, CHAIN_ID }) => {
      // 新增插件
      chain.plugin('custom-define').use(bundler.DefinePlugin, [
        {
          'process.env': {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV),
          },
        },
      ]);

      // 修改插件
      chain.plugin(CHAIN_ID.PLUGIN.HMR).tap((options) => {
        options[0].fullBuildTimeout = 200;
        return options;
      });

      // 删除插件
      chain.plugins.delete(CHAIN_ID.PLUGIN.HMR);
    },
  },
};

根据环境修改

tools.bundlerChain 函数的第二个参数中,你可以拿到各种环境的标识,如开发/生产模式构建、 SSR 构建、Web Worker 构建,从而实现不同环境下的配置修改。

rsbuild.config.mjs
export default {
  tools: {
    bundlerChain: (chain, { env, isProd, target, isServer, isWebWorker }) => {
      if (env === 'development' || env === 'test') {
        // ...
      }
      if (isProd) {
        // ...
      }
      if (target === 'node') {
        // ...
      }
      if (isServer) {
        // ...
      }
      if (isWebWorker) {
        // ...
      }
    },
  },
};

以上是一些常见的配置示例,完整的 API 请见 rspack-chain 文档

配置修改顺序

Rsbuild 支持通过 tools.rspacktools.bundlerChainmodifyBundlerChain 等方式修改 Rspack 配置对象。

它们之间的执行顺序依次为: