Webpack5+SingleSpa环境下@svgr/webpack无法转换SVG为React组件
解决SingleSpa React TS项目中@svgr/webpack无法将SVG转为React组件的问题
在基于Single Spa Playground新建的React TS项目中,其他功能正常,但无法通过@svgr/webpack将SVG转换为React组件。当前SVG被处理为URL而非组件,无法通过props修改fill属性,手动创建组件成本过高。
报错信息
- 直接导入SVG后以组件形式渲染
<TestImg />无效果,打印TestImg显示为URL - 尝试命名导入
import { ReactComponent as TestImg } from "../../assets/icons/testimage.svg"时,报错:无法从默认导出的模块中导入命名导出'ReactComponent'(导入为'TestImg')(仅默认导出可用)
问题根源
webpack-config-single-spa-react-ts生成的默认配置中,已包含对SVG文件的处理规则(通常使用url-loader或file-loader),导致自定义的@svgr/webpack规则被覆盖,SVG仍然被当作资源文件处理而非转换为React组件。
解决方案
方案1:过滤默认配置中的SVG规则,添加自定义规则
修改webpack.config.js,先移除默认配置里处理SVG的规则,再添加@svgr/webpack的处理规则:
const webpackMerge = require("webpack-merge").merge; const singleSpaDefaults = require("webpack-config-single-spa-react-ts"); module.exports = (webpackConfigEnv, argv) => { const defaultConfig = singleSpaDefaults({ orgName: "testorg", projectName: "testproj", webpackConfigEnv, argv, }); // 过滤掉默认配置中处理.svg的规则 defaultConfig.module.rules = defaultConfig.module.rules.filter(rule => { if (rule.test) { return !rule.test.test('.svg'); } return true; }); return webpackMerge(defaultConfig, { module: { rules: [ { test: /\.s[ac]ss$/i, use: ["style-loader", "css-loader", "sass-loader"], }, { test: /\.svg$/, use: ["@svgr/webpack"], }, ], }, }); };
方案2:使用oneOf确保@svgr规则优先处理
如果默认配置里的规则在oneOf数组中,可将@svgr/webpack的规则放在oneOf最前面,确保优先匹配:
const webpackMerge = require("webpack-merge").merge; const singleSpaDefaults = require("webpack-config-single-spa-react-ts"); module.exports = (webpackConfigEnv, argv) => { const defaultConfig = singleSpaDefaults({ orgName: "testorg", projectName: "testproj", webpackConfigEnv, argv, }); // 在oneOf数组最前面添加@svgr规则 if (defaultConfig.module.rules[0].oneOf) { defaultConfig.module.rules[0].oneOf.unshift({ test: /\.svg$/, use: ["@svgr/webpack"], }); } return webpackMerge(defaultConfig, { module: { rules: [ { test: /\.s[ac]ss$/i, use: ["style-loader", "css-loader", "sass-loader"], }, ], }, }); };
方案3:同时支持组件导入和资源导入(可选)
如果需要同时支持将SVG作为组件和资源导入,可配置@svgr/webpack与url-loader结合:
{ test: /\.svg$/, use: [ { loader: '@svgr/webpack', options: { svgo: false, // 可选:关闭SVGO优化,保留原始SVG结构 }, }, 'url-loader', ], }
对应导入方式:
- 组件导入:
import TestImg from "../../assets/icons/testimage.svg" - 资源导入:
import testImgUrl from "../../assets/icons/testimage.svg?url"
类型声明调整
确保declarations.d.ts的类型声明与导入方式匹配:
// 默认导出组件的类型声明 declare module "*.svg" { const content: React.FC<React.SVGAttributes<SVGElement>>; export default content; } // 同时支持url导入时添加 declare module "*.svg?url" { const content: string; export default content; }
验证修改
- 重启webpack开发服务器
- 导入SVG并作为组件使用:
import TestImg from "../../assets/icons/testimage.svg"; // 使用时可传递props修改样式 <TestImg fill="#ff0000" width={200} height={200} />
内容的提问来源于stack exchange,提问作者AFrequentVisitor
相关产品推荐
相关产品推荐

