SVGO 压缩 SVG 后不能正常缩放
前情提要
在前端开发过程中,SVG 图标(可缩放矢量图形)被广泛使用,因为它们具有可伸缩性、清晰的显示效果以及较小的文件大小。使用 SVG 作为图标有很多优势,尤其是在响应式设计和高分辨率屏幕上的表现。
但是,SVG 图标的制作过程也有很多不便之处。一千个读者就有一千个哈姆雷特,一千个制作者绘制同一个图标也可能会有一千个不同的版本。尽管 SVG 本身已经足够小了,但是在很多矢量编辑器/软件中,导出来的 SVG 文件会有很多其他冗余信息(当然这里面制作者和导出软件可能都会有问题)。
为了解决这些问题,我们需要一个工具来压缩 SVG 图标,使其更小、更清晰、更易于管理。所以选择了 SVGO 对图片进行压缩并且使用 SVGR 将 SVG 代码转换为 React Component 。
你可以在这尝试进行 svg 的压缩与转化。
ps: scgr 会默认使用 svgo 帮你压缩 svg 代码。
npx @svgr/cli --typescript --out-dir ./svgicons -- svgrz
压缩效果也是显著:
但是在使用的时候发现了一个问题,有一部分压缩完的 SVG 不能设置宽高,如果设置了宽高,会导致 svg 只有一部分展示。
问题原因
检查 SVG 代码发现,viewBox 标签不见了。删除掉 viewBox 会导致 SVG 不能正常缩放。可以说这属于是破环性的压缩,很难理解 svgo 为了 “minimizing number of bytes” 而删除 viewBox 标签。
因为对于 SVG 规范了解的并不够深入,所以不能确定 svgo 压缩是否是正确的,查看 issues 发现很多前端开发都提出了这个问题,但 svgo 似乎并不像修改。
解决方案
为了解决这个问题,在压缩 SVG 代码时,我们需要通过配置文件来保留 viewBox 标签。
添加 svgo.config.js
文件
export default {
plugins: [
{
name: "preset-default",
params: { overrides: { removeViewBox: false } },
},
],
};
因为 SVGR 会默认使用 SVGO 进行压缩,所以我们需要使用 --no-svgo
禁止 SVGR 的压缩操作
svgo -f svg/ -o svgrz/ && npx @svgr/cli --typescript --out-dir ./svgicons --no-svgo -- svgrz
到这里,SVG 图标的压缩与转化就完成了。
参考资料
更多关于 SVGO 压缩 viewBox 标签的讨论:
issue 1461
issue 1128