You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

验证修改

  1. 重启webpack开发服务器
  2. 导入SVG并作为组件使用:
import TestImg from "../../assets/icons/testimage.svg";

// 使用时可传递props修改样式
<TestImg fill="#ff0000" width={200} height={200} />

内容的提问来源于stack exchange,提问作者AFrequentVisitor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:05:17