Nx 23 迁移指南用withSvgr组合函数替代 Rspack 配置中的svgr选项【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx导读本文聚焦 Nx Monorepo 中nx/rspack插件的一次破坏性配置变更自 Nx 23.0.0 起withReact与NxReactRspackPlugin上的svgr选项被移除SVG 处理统一收敛到默认的 images asset 规则SVGRSVG 转 React 组件能力改由新的withSvgr组合函数提供。你将掌握这条迁移的完整背景、withSvgr的底层实现原理、两种配置风格withReact组合式与NxReactRspackPlugin插件式的具体改写方法以及迁移工具自动执行时的边界行为与验证依据。迁移背景为什么移除svgr选项在 Nx 23.0.0 之前的 Rspack 配置中要启用「将 SVG 文件作为 React 组件导入」的能力需要在withReact或NxReactRspackPlugin中显式传入svgr选项例如withReact({ svgr: { svgo: false, titleProp: true, ref: true } })或new NxReactRspackPlugin({ svgr: true })。从源码结构看这一设计存在两个问题职责耦合SVG 的加载策略被塞进 React 相关的 helper/plugin 中与「React 支持」这一核心职责无关规则覆盖默认的 images asset 规则见 apply-web-config.ts其test为/\.(avif|bmp|gif|ico|jpe?g|png|svg|webp)$/本身已包含svg额外注入的 SVGR 规则容易与之发生语义冲突行为不易预测。因此 Nx 23 决定SVG 作为普通图片资源的加载即*.svg?url形式由默认 images asset 规则统一承担而 SVGR-as-React-component 的行为则抽离为独立的withSvgr组合函数由迁移工具把 helper 内联进每个受影响的配置文件确保原有行为不丢失。该迁移在 migrations.json 中注册为update-23-0-0-add-svgr-to-rspack-config版本号23.0.0-beta.9description 明确写着Updates rspack configs using React to use the new withSvgr composable function instead of the svgr option随nx migrate自动触发。场景一withReact组合式配置的改写withReact风格即composePlugins组合方式的迁移目标是把svgr选项从withReact(...)中删除将withSvgr(...)作为新的组合项追加在withReact()之后。迁移前Beforeconst { composePlugins, withNx, withReact } require(nx/rspack); module.exports composePlugins( withNx(), withReact({ svgr: { svgo: false, titleProp: true, ref: true } }) );迁移后Afterconst { composePlugins, withNx, withReact } require(nx/rspack); // SVGR support function (migrated from svgr option in withReact/NxReactRspackPlugin) function withSvgr(svgrOptions {}) { const defaultOptions { svgo: false, titleProp: true, ref: true }; const options { ...defaultOptions, ...svgrOptions }; return function configure(config) { const svgLoaderIdx config.module.rules.findIndex( (rule) typeof rule object typeof rule.test ! undefined rule.test.toString().includes(svg) ); if (svgLoaderIdx ! -1) { config.module.rules.splice(svgLoaderIdx, 1); } config.module.rules.push( { test: /\.svg$/i, type: asset, resourceQuery: /url/ }, { test: /\.svg$/i, issuer: /\.[jt]sx?$/, resourceQuery: { not: [/url/] }, use: [{ loader: svgr/webpack, options }], } ); return config; }; } module.exports composePlugins( withNx(), withReact(), withSvgr({ svgo: false, titleProp: true, ref: true }) );需要特别注意的是withSvgr返回的是configure(config)形式的配置转换函数与composePlugins中的withNx、withReact属于同一抽象层级因此可以直接并列传入。上例中传给withSvgr的选项对象与原先svgr选项完全一致svgo: false, titleProp: true, ref: true因为迁移逻辑会把原svgr对象中的布尔属性逐字保留。场景二NxReactRspackPlugin插件式配置的改写NxReactRspackPlugin风格普通 rspack 配置对象 plugins 数组的迁移路径不同svgr选项从插件构造参数中移除整个module.exports或export default被withSvgr(...)({...})包裹——因为此时没有composePlugins可用withSvgr直接以高阶函数形式包裹整个配置对象通过向plugins追加一个 compiler 插件来注册 loader 规则。迁移前Beforeconst { NxReactRspackPlugin } require(nx/rspack); module.exports { plugins: [new NxReactRspackPlugin({ svgr: true, main: ./src/main.tsx })], };迁移后Afterconst { NxReactRspackPlugin } require(nx/rspack); // SVGR support function (migrated from svgr option in withReact/NxReactRspackPlugin) function withSvgr(svgrOptions {}) { const defaultOptions { svgo: false, titleProp: true, ref: true }; const options { ...defaultOptions, ...svgrOptions }; return (config) { config.plugins.push({ apply: (compiler) { // Remove ALL existing SVG loaders compiler.options.module.rules compiler.options.module.rules.filter( (rule) !( rule typeof rule object rule.test rule.test.toString().includes(svg) ) ); compiler.options.module.rules.push( { test: /\.svg$/i, type: asset, resourceQuery: /url/ }, { test: /\.svg$/i, issuer: /\.[jt]sx?$/, resourceQuery: { not: [/url/] }, use: [{ loader: svgr/webpack, options }], } ); }, }); return config; }; } module.exports withSvgr()({ plugins: [new NxReactRspackPlugin({ main: ./src/main.tsx })], });注意此处的withSvgr模板与场景一不同两者分别定义于迁移源码 add-svgr-to-rspack-config.ts 与 add-svgr-to-rspack-config.ts插件式版本返回(config) config通过config.plugins.push({ apply: (compiler) ... })在webpack/rspack compiler 层面修改compiler.options.module.rules并且使用filter清除所有已存在的 SVG loader 规则而非仅第一条再追加两条新规则。这是因为插件式配置中 SVG 规则可能由其他插件如NxAppRspackPlugin注入需要全量清理后才能保证 SVGR 规则的唯一性。withSvgr的工作原理两条规则的分工无论哪种风格withSvgr最终都会在module.rules中注册两条规则它们共同构成完整的 SVG 处理管线规则testissuerresourceQuery处理方式语义1/\.svg$/i—/url/type: assetimport logo from ./logo.svg?url时按普通资源处理返回文件 URL2/\.svg$/i/\.[jt]sx?$/{ not: [/url/] }svgr/webpackloader从 JS/TS(X) 文件默认导入 SVG 时转为 React 组件issuer: /\.[jt]sx?$/限定只有从.js/.jsx/.ts/.tsx文件发起的导入才走 SVGR避免 CSS 等其他文件引用 SVG 时被错误转换resourceQuery: { not: [/url/] }明确排除?url形式与规则 1 形成互补确保两种导入方式互不干扰type: asset是 rspack/webpack 5 的资源模块类型配合默认的 images asset 规则实现「小图内联、大图外链」的自动行为。两条规则中options均来自{ ...defaultOptions, ...svgrOptions }的浅合并默认值svgo: false不做 SVG 优化压缩保留原始结构、titleProp: true允许通过titleprop 注入title、ref: true透传ref到根节点与 Nx 23 之前svgr选项的默认语义保持一致。迁移工具的自动化机制与边界行为整个迁移由 add-svgr-to-rspack-config.ts 实现其执行流程可分为三步全部基于 TypeScript AST 而非文本替换第一步定位目标项目。通过forEachExecutorOptions(tree, nx/rspack:rspack, ...)遍历所有使用nx/rspack:rspackexecutor 的 target读取其rspackConfig指向的配置文件再分别检测文件内容中是否包含withReact或NxReactRspackPlugin用 tsquery 的CallExpression[expression.namewithReact]与NewExpression[expression.nameNxReactRspackPlugin]选择器精确匹配调用点见 add-svgr-to-rspack-config.ts。第二步解析svgr选项值。迁移支持三种取值形态svgr: true→ 迁移后调用withSvgr()不传参使用默认选项svgr: { svgo: true, titleProp: false, ref: false }→ 将对象中的布尔属性逐字保留生成withSvgr({ svgo: true, titleProp: false, ref: false })svgr: false→ 仅删除该属性不注入withSvgr保持 SVGR 关闭状态。第三步按风格改写并格式化。对于withReact风格若svgr是唯一参数则整个对象参数被删除withReact()否则精确删除该属性并保留逗号语法正确的其他属性对于插件风格删除插件参数中的svgr属性后找到module.exports ...或export default ...的导出表达式在其前后分别插入withSvgr(...)(与)完成包裹见 add-svgr-to-rspack-config.ts。所有改动通过applyChangesToString一次性应用最后调用formatFiles统一代码格式。该迁移对以下边界情况的处理均有测试用例覆盖见 add-svgr-to-rspack-config.spec.ts未使用svgr的配置完全不改动含svgr: false与注释掉的选项测试见「should not modify configs without svgr option」保留withReact的其他选项如withReact({ svgr: true, stylePreprocessorOptions: {...} })迁移后stylePreprocessorOptions原样保留支持 CJSrequiremodule.exports与 ESMimportexport default两种模块格式支持module.exports config变量引用形式helper 插入在 import/require 语句之后、withSvgr包裹施加在导出的变量表达式上多项目工作区仅迁移实际使用了svgr的配置其余项目如纯withReact()不受影响见「should handle multiple rspack configs in workspace」。迁移后的注意事项与验证1. 依赖要求withSvgr内联 helper 依赖svgr/webpackloader规则中use: [{ loader: svgr/webpack, options }]。迁移本身不会修改package.json因此请确认项目中已安装svgr/webpack迁移前使用svgr: true的项目通常已具备该依赖但建议迁移后执行一次干净的安装并运行nx build app验证。2. 迁移后的显式声明优于隐式依赖迁移完成后的配置文件是自包含的withSvgr函数直接内联在rspack.config.js中不依赖nx/rspack的任何导出。这意味着后续即使nx/rspack移除相关内部实现配置依然可用同时你可以在内联函数中直接修改默认选项例如将svgo改为true启用 SVG 优化。3.withReact本身的弃用顺带一提从 with-react.ts 的 JSDoc 可以看到withReact已被标记为deprecated计划在 Nx v24 移除官方推荐迁移到NxReactRspackPlugin位于 nx-react-rspack-plugin.ts并在标准 rspack 配置中使用nx g nx/rspack:convert-to-inferred转换。如果你的配置已经或即将采用插件式风格本次withSvgr迁移同样覆盖了这一路径。4. 回归验证建议迁移后重点验证以下场景# 构建验证以 React 应用为例 nx build myapp # 快速冒烟确认 SVG 组件与 ?url 两种导入均可用建议在迁移后的 PR 中检查import Logo from ./logo.svgSVGR 组件形式能正常渲染、import logoUrl from ./logo.svg?url返回资源地址、以及 CSS 中background: url(...svg)不受影响其导入来自 CSS 文件不满足issuer条件走默认 asset 规则。总结Nx 23 的这次迁移本质是一次关注点分离的重构SVG 作为静态资源由默认 images asset 规则统一负责SVGR 的 React 组件化能力则独立成withSvgr组合函数并内联进配置文件。无论你的项目使用withReact组合式还是NxReactRspackPlugin插件式配置nx migrate都会通过 AST 精确改写完整保留原有svgr选项含布尔值与自定义对象的语义同时兼顾 CJS/ESM、变量导出、多项目等边界场景。理解withSvgr内部「删除旧 SVG 规则 → 注册type: assetsvgr/webpack双规则」的机制能帮助你在迁移后对 SVG 加载行为有完全的掌控力。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考