框架适配总览:React、Vue、Svelte 与通用规则

先区分 core 和模板

讨论 Rslib 对框架的支持时,要先区分两层:

层级位置职责
core 层packages/core通用库构建规则,以及少量会影响产物正确性的框架特判
模板层packages/create-rslib/template-*给 React、Vue、Svelte 项目装对应 Rsbuild 插件、测试工具和 dts 辅助

很多“Rslib 支持 React/Vue/Svelte”的能力其实在模板层。例如 React 模板使用 @rsbuild/plugin-react,Vue 模板使用 @rsbuild/plugin-vue,Svelte 模板使用 @rsbuild/plugin-svelte。这些不等于 core 里有框架 hack。

Core 里真正值得注意的是那些为了库产物正确性而写的特殊分支。

总览表

框架或生态core 是否有明确特判特判是什么主要原因
Vue SFCrspack-vue-loader 虚拟请求放行避免 bundleless 产物泄露 loader 内部 request
React JSX有边界校验bundle 模式禁止 preserve JSXbundle 产物不能保留 JSX 源语法
SVGRpatch URL publicPath,区分资源 URL 和 ReactComponent库产物不能用应用 runtime publicPath
CSS Modules通用处理bundleless 下 CSS Modules 指向 JS mappingReact/Vue/Svelte 都可能用,不是框架专属
Sveltecore 无明确特判模板使用 pluginSvelte 和 svelte2tsx dts 插件当前没有发现 loader 内部 request 需要 core 过滤

Vue:为什么是明确 hack

Vue SFC loader 会生成内部 request,例如:

rspack-vue-loader/dist/exportHelper.js
Button.vue?vue&type=script&setup=true
Button.vue?vue&type=template
Button.vue?vue&type=style

这些 request 出现在 Rspack 模块图里,会经过 bundleless external 的拦截点。Rslib 不能把它们当普通源码 import 保留到产物中,因为消费者不应该看到 rspack-vue-loader 的内部实现。

所以 core 中专门识别 rspack-vue-loader,对 dist/exportHelper.js?vue&type= 放行,让 Rspack 正常 bundle 这些内部模块。

这是明确的 Vue-specific hack。

React:主要是 JSX 和 SVGR

React 相关的 core 逻辑不是“看到 React 就特殊处理”,而是围绕 React 生态常见产物形态:

  1. JSX preserve。
  2. SVGR。
  3. react/jsx-runtime external。

JSX preserve

React 组件库有时希望保留 JSX 源语法,让下游继续编译。但 Rslib 只允许 bundleless preserve JSX,不允许 bundle preserve JSX。因为 bundle 产物应是可执行 JS bundle,里面保留 JSX 会让运行时不可用。

这不是只服务 React,但实际主要影响 React。

SVGR

SVGR 会把 SVG 转成 React component,但 mixed import 还会同时生成资源 URL。Core 的特殊处理主要是 URL 部分,不是 React component 部分。

Svelte:为什么目前没有 core hack

Svelte 模板通过 @rsbuild/plugin-svelte 接入。TS 模板还有 svelte2tsx dts 插件。当前 core 没有发现需要识别 svelte-loader 内部 request 的逻辑。

这里不是说 Svelte 永远不需要 hack,而是当前仓库的实现和测试没有暴露类似 Vue 的问题。Svelte loader 输出的模块图没有以同样方式把 loader 内部 block request 泄露到 bundleless external 重写流程里。

另一个现实原因是:Rslib 的 Svelte 模板默认不是 bundleless。它配置的是普通 ESM bundle。这也减少了触发 bundleless external 冲突的机会。

通用规则覆盖了很多框架需求

很多框架组件库需求并不是框架特判,而是通用库构建能力:

  • peer dependency external。
  • CSS extract。
  • CSS Modules。
  • asset emit。
  • bundleless source structure。
  • dts 输出。
  • target web。

例如 React 和 Vue 都需要 CSS 被正确抽取,Svelte 也可能需要 CSS 输出;这不需要分别写 React/Vue/Svelte 三套逻辑,而是 CSS 子系统统一处理。

判断是否需要新增框架 hack

新增框架 hack 应该非常谨慎。只有满足下面条件时才考虑:

  1. loader 产生的内部 request 会进入 Rslib bundleless external 或 asset 规则。
  2. 这些 request 如果保留到产物中,会让消费者依赖 loader 内部实现。
  3. 通用规则无法区分它和用户源码 import。
  4. 有最小复现和 integration test。
  5. 特判范围足够窄,不会误伤用户正常 import。

Vue 的 rspack-vue-loader 特判满足这些条件。Svelte 当前没有。

修改风险

框架 hack 的风险在于它很容易绑定 loader 内部实现。loader 升级后 request 字符串可能变化,Rslib 的判断就会失效。

因此这类逻辑应:

  • 写在离冲突机制最近的地方。
  • 用清楚注释说明为什么存在。
  • 有真实框架 fixture 测试。
  • 尽量匹配具体 loader 包名和具体 request pattern。
  • 不要用过宽的规则,例如只要 request 包含 vue 就放行。