如何在React Vite中使用SVGR导入public目录下的SVG文件?
解决React+Vite+SVGR导入public目录SVG并修改属性的问题
问题场景
我用React + Vite + SVGR开发项目,SVG文件放在public目录下,结构如下:
| |- src |- public |- icons |- svgs |- mySvg.svg |- vite.config.ts |- package.json
导入SVG时触发Vite报错:
public目录中的资源无法从JavaScript导入。
如果您打算导入该资源,请将文件放在src目录中,并使用/src/assets/icons/svgs/mySvg.svg代替/public/assets/icons/svgs/mySvg.svg。
同时有两个限制:
- 不能用
<img>标签引入SVG(需要修改SVG的属性,比如颜色、尺寸) - 不能把SVG移到src目录(希望保留public作为标准资源目录,兼容其他库的内置支持)
解决方案一:配置Vite+SVGR直接导入public目录SVG
1. 确认依赖安装
确保已安装SVGR相关插件:
npm install @svgr/core vite-plugin-svgr --save-dev
2. 修改Vite配置文件
在vite.config.ts中调整SVGR插件的匹配规则,让它覆盖public目录的SVG:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; import path from 'path'; export default defineConfig({ plugins: [ react(), svgr({ // 匹配public目录下的所有SVG文件,路径根据项目根目录调整 include: path.resolve(__dirname, 'public/icons/svgs/**/*.svg'), // SVGR的额外配置,比如启用title属性支持 svgrOptions: { titleProp: true, }, }), ], // 配置路径别名,简化导入路径 resolve: { alias: { '@public': path.resolve(__dirname, 'public'), }, }, });
3. 导入并使用SVG组件
现在可以直接把SVG作为React组件导入,还能通过props修改属性:
import MySvg from '@public/icons/svgs/mySvg.svg?react'; function App() { return ( <div> {/* 直接修改SVG的fill、width等属性 */} <MySvg fill="#ff4444" width="50" height="50" /> </div> ); } export default App;
解决方案二:动态加载并解析SVG(无需修改Vite配置)
如果不想调整Vite配置,可以通过fetch动态加载SVG并解析为可修改属性的React元素:
import { useEffect, useState } from 'react'; function CustomSvg({ src, ...props }) { const [svgNode, setSvgNode] = useState(null); useEffect(() => { const loadAndParseSvg = async () => { const res = await fetch(src); const svgContent = await res.text(); const parser = new DOMParser(); const svgDoc = parser.parseFromString(svgContent, 'image/svg+xml'); const svgElement = svgDoc.querySelector('svg'); if (svgElement) { // 将传入的props转为SVG属性 Object.entries(props).forEach(([key, val]) => { svgElement.setAttribute(key, String(val)); }); // 转为React元素渲染 setSvgNode( <svg {...props} dangerouslySetInnerHTML={{ __html: svgElement.innerHTML }} /> ); } }; loadAndParseSvg(); }, [src, props]); return svgNode || <div>Loading...</div>; } // 使用示例 function App() { return ( <div> <CustomSvg src="/icons/svgs/mySvg.svg" fill="#22aaee" width="60" /> </div> ); }
这个方案适合不想改动构建配置的场景,但需要处理SVG加载的异步状态。
内容的提问来源于stack exchange,提问作者Noy Oliel
相关产品推荐
相关产品推荐

