vite里带渐变的svg渲染失败
背景
vite 项目使用 svg 渲染失败
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M9.03063 9.07812C10.6708 9.07812 12.1368 10.1017 12.7015 11.6416L12.892 12.1631C13.1256 12.8008 12.6542 13.4764 11.975 13.4766H4.02184C3.3426 13.4766 2.8704 12.8008 3.10388 12.1631L3.29528 11.6416C3.86003 10.1018 5.32605 9.07812 6.96618 9.07812H9.03063ZM7.99938 2.47656C9.51198 2.47656 10.7386 3.70322 10.7386 5.21582C10.7384 6.72821 9.51183 7.9541 7.99938 7.9541C6.48698 7.95405 5.26135 6.72818 5.2611 5.21582C5.2611 3.70325 6.48683 2.47662 7.99938 2.47656Z" fill="url(#paint0_linear_8810_5731)"/>
<defs>
<linearGradient id="paint0_linear_8810_5731" x1="4.57835" y1="0.179964" x2="6.53322" y2="8.97691" gradientUnits="userSpaceOnUse">
<stop stop-color="#666666"/>
<stop offset="1"/>
</linearGradient>
</defs>
</svg>
原因
如果你项目里使用了 SVG Loader 转组件(比如 vite-svg-loader 或 @svgr/webpack),SVG loader 默认会 自动重写或去掉<defs>,导致 url(#paint0_linear_8810_5731) 无法找到对应 gradient,显示为空白。
解决
给 vite-svg-loader 添加 svgoConfig 保留<defs>
vitePlugins.push(svgLoader({svgoConfig: {plugins: [// 使用 preset-default 并禁用 cleanupIds 插件,保留 SVG 中的所有 id(如 clipPath、linearGradient、mask 等){name: 'preset-default',params: {overrides: {cleanupIds: false, // 禁用 cleanupIds 插件(注意是小写 's')},},},],},}),)
过程中问了gpt给出的各种配置因为ts类型检测的问题都不行,最后在cursor指出准确问题解决掉了
另一种简单粗暴方案,直接禁用 SVGO
vitePlugins.push(svgLoader({ svgo: false }))
- svgo: false 表示不让 loader 去优化 SVG。
- 优点:保证 Figma 导出的
<linearGradient>、<defs>正常工作。 - 缺点:SVG 不会压缩,但对大多数项目影响很小。
