库配置编排

入口函数

packages/core/src/config.ts 是 Rslib 最核心的文件。它的主链路是:

维护者应优先理解 composeLibRsbuildConfig。它读取一个已经合并共享配置的 LibConfig,再按模块组合出最终 Rsbuild environment。

composeLibRsbuildConfig 组成项

组成项函数解决的问题
bundle 模式检查composeBundleConfigbundle 模式下阻止不支持的 preserve JSX
格式输出composeFormatConfig为 ESM、CJS、UMD、IIFE、MF 设置 Rspack output、parser、runtime、library
targetcomposeTargetConfig区分 node 和 web,处理 Node builtins external
shimscomposeShimsConfig为 CJS 注入 import.meta.*,为 ESM 注入 __dirname__filenamerequire
文件名composeOutputFilenameConfig根据 format、package type、autoExtension 推导 JS 和 dts 扩展名
entrycomposeEntryConfigbundle 模式校验文件入口,bundleless 模式展开 glob
bundleless externalcomposeBundlelessExternalConfig将源文件之间的引用重写为输出路径
auto externalcomposeAutoExternalConfig根据 package.json external 依赖
dtscomposeDtsConfig挂载 rsbuild-plugin-dts
CSScomposeCssConfigbundleless 中处理 CSS modules、全局 CSS 和 extract
资源composeAssetConfig处理资源 import preserve 和 CSS url
entry chunkcomposeEntryChunkConfig注入 import.meta.url shim,并注册 watch context
minifycomposeMinifyConfig设置默认 dead code 和 unused code 删除
banner/footercomposeBannerFooterConfig注入 JS、CSS banner/footer
decoratorscomposeDecoratorsConfig从 tsconfig 推断 legacy decorators
execomposeExeConfig挂载实验性 Node SEA 可执行文件生成

格式派生

composeFormatConfig 针对不同 format 给 Rspack 设置不同输出语义:

format输出语义关键点
esmmodern moduleoutput.module = truelibrary.type = modern-module,chunk loading 使用 import
cjscommonjs-staticlibrary.type = commonjs-static,chunk loading 使用 require
umdUMD bundle必须 bundle: true,关闭 async chunks 和 splitChunks
iifemodule library IIFE必须 bundle: trueglobalObject = globalThis,关闭 async chunks
mfModule Federation必须 bundle: true,更像 web app,设置 writeToDiskuniqueName

ESM 和 CJS 都会挂载 Rspack 的实验性 RslibPlugin。MF 由于需要应用式 runtime,不使用内置 Rslib plugin。

目标平台

composeTargetConfig 默认规则:

  • format: "mf" 默认 web
  • 其他格式默认 node

当 target 为 node 时,Rslib 设置:

  • tools.rspack.target = ["node"]
  • output.target = "node"
  • externalsPresets.node = false
  • 将 Node built-in modules 作为 externals

当 target 为 web 时,Rslib 设置 tools.rspack.target = ["web"],不自动 external Node builtins。

Entry 处理

Bundle 模式

bundle 模式下,如果用户没有配置 entry,Rslib 让 Rsbuild 使用默认 entry。用户配置 entry 时,Rslib 会校验每个入口必须是文件,不支持目录或 glob。如果传入 glob,会抛错并提示切换到 bundle: false

Bundleless 模式

bundleless 模式下,如果用户没有配置 entry,默认使用:

{
  index: 'src/**',
}

随后 Rslib 会用 tinyglobby 展开 glob,并过滤 .d.ts 等声明文件。输出 entry name 基于 outBase 的相对路径保留目录结构:

outBase 默认是所有非声明输入文件的最长公共路径,也可由用户配置。全局 CSS entry 会加上 __rslib_css__ 标记,后续 CSS 插件会删除对应的空 JS asset。

外部化顺序

Rslib 合并 externals 的顺序非常关键:

  1. externalsWarnConfig:先探测 ESM 中 externalized commonjs request,必要时提示用户设置 external type。
  2. userExternalsConfig:用户显式 external 优先。
  3. autoExternalConfig:根据 package.json 依赖自动 external。
  4. targetExternalsConfig:node target 下 external Node builtins。
  5. bundlelessExternalConfig:最后处理源文件内部相对路径重写。

这个顺序保证 bundleless 重写只处理前面没有命中的源码内部依赖。如果用户 external 了某个包,bundleless 不会再尝试把它解析成相对文件。

Auto External

composeAutoExternalConfig 只在 bundle: true 时生效。默认值由格式决定:

  • ESM 和 CJS 属于中间产物格式,默认启用 autoExternal。
  • UMD、IIFE、MF 更偏最终运行产物,默认不启用。

默认 external 的依赖类型:

依赖类型默认
dependenciestrue
peerDependenciestrue
optionalDependenciestrue
devDependenciesfalse

用户显式 output.externals 为对象时,相关 key 会从 auto external 结果里排除,避免同一个依赖被重复或冲突处理。

Bundleless Redirect

composeBundlelessExternalConfig 是 bundleless 的关键逻辑。它通过 Rspack external function 拦截模块请求:

  1. 跳过 entry module,只处理有 issuer 的依赖。
  2. 确认 issuer 或 context 位于 outBase 内,避免改写 node_modules 内部请求。
  3. 对 Vue loader 生成的虚拟请求和 helper 放行,避免 loader 内部路径泄露到产物。
  4. 用 resolver 解析请求。
  5. 如果解析结果仍在 outBase 内,转成相对于 issuer 的输出路径。
  6. CSS 请求交给 cssExternalHandler
  7. JS 和 asset 请求根据 redirect.jsredirect.assetautoExtension 改写路径和扩展名。

这个逻辑同时覆盖无扩展名 import、目录 import、TS 到 JS 扩展名替换、非 JS 资源转 JS import 等情况。

CSS 处理

packages/core/src/css/cssConfig.ts 只在 bundleless 且存在 outBase 时启用。它做两类事:

  • 替换 Rsbuild 默认 CSS extract loader 为 libCssExtractLoader,并替换 CSS extract plugin 为 LibCssExtractPlugin
  • processAssets 早期删除全局 CSS entry 对应的虚拟 JS asset,但保留 CSS Modules 需要的 JS asset。

cssExternalHandler 的重写规则:

输入输出
CSS Modules import指向对应 JS 扩展名,如 .module.scss.mjs
全局 CSS import指向 .css
CSS 文件内部 asset import不 external,交给 CSS 处理
css-loader helper不 external,保持内部执行

资源处理

packages/core/src/asset/assetConfig.ts 对 ESM 和 CJS 生效,默认设置 dataUriLimit: 0assetPrefix: "auto"

pluginLibAsset 主要处理:

  • 对 JS issuer 的资源设置 importMode: "preserve",让库产物保留资源引用。
  • 对 CSS issuer 复制一份 asset rule,避免 CSS url 受 JS 资源 preserve 逻辑影响。
  • 针对 SVGR 修补 publicPath,移除不适合库产物的 __webpack_require__.p
  • bundleless 中不支持 SVG query import 时调整 issuer。
  • bundle 模式下设置 CSS extract 的 enforceRelative,保留 CSS url 的相对路径。

文件扩展名和 runtime chunk

composeOutputFilenameConfig 会调用 getDefaultExtension,根据 format、package.json 和 autoExtension 推导 JS 和 DTS 扩展名。它还会为多 compiler 情况推导 chunk filename,避免多个 environment 输出 chunk 名冲突。

getRuntimeChunkConfig 的规则:

  • bundleless 始终使用 rslib-runtime
  • bundle 模式单入口不单独设置 runtimeChunk。
  • bundle 模式多入口使用 rslib-runtime,多 compiler 时加 compiler index 前缀。

Minify 默认值

如果用户没有设置 output.minify,Rslib 提供保守默认值:

  • 启用 JS minify 管线。
  • 不 mangle。
  • 只做 unused 和 dead code 删除。
  • 保留注释中的部分注解。
  • MF 格式会开启更完整的 minify,因为远程资源通常经网络加载,不一定由项目侧压缩。

维护检查点

  • 修改 composeLibRsbuildConfig 新增配置项时,确认它在最终 mergeRsbuildConfig 的位置是否正确。
  • 新增 format 时必须更新 Format 类型、composeFormatConfigcomposeExternalsConfigcomposeTargetConfig 相关分支、测试工具和文档。
  • 修改 bundleless 时至少检查 JS redirect、CSS redirect、asset redirect、dts redirect 和 watch 行为。
  • 修改 external 行为时重点跑 tests/integration/externalsauto-externalredirectbundle-falsesource-phase 类似覆盖点。