跳到主要内容

SVG 优化的边界:什么该删,什么碰一下就会坏

· 3 分钟阅读
Connexion Collective
ADMIN 权限狗

设计工具导出的 SVG 通常有两种体积:你看到的那张图,和文件里真实存在的东西。

一张 800 字节的图标,能把 500 多字节花在没人要的元数据上。但清理时必须清楚哪些是垃圾、哪些是命脉。

可以安全删掉的​

内容例子
XML 声明<?xml version="1.0"?>
注释<!-- Generator: Adobe Illustrator 27.0.0 -->
DOCTYPE大多数情况下与渲染无关
元数据块<metadata> 里塞的 RDF/DC 版权信息
编辑器专用元素<sodipodi:namedview inkscape:zoom="1.5">
编辑器专用属性inkscape:label、sodipodi:role
空组<g></g>
标签之间的空白压缩后渲染结果完全相同

这类东西删掉后,浏览器渲染的画面一个像素都不会变。

绝对不能动的​

  • id 和所有引用:<use href="#a">、url(#grad)、clip-path、filter、mask,删掉 id 就是白板。
  • xlink:href:老格式的引用,保留原样最稳。
  • <defs> 里的内容:看着"没被渲染",其实全是资源。
  • viewBox 的数值语义:精度可以降,但比例不能变。

所以我只删「确定与渲染无关」的东西,绝不重写路径数据 —— 那属于另一类优化(曲线拟合),风险高得多。

一个真实踩到的坑:删属性不够,得删元素​

第一版实现里,我用正则删掉了 inkscape: / sodipodi: 前缀的属性,以为干净了。结果优化后的文件里还留着 <sodipodi:namedview/> 这个元素 —— 它没有子内容,但带着一堆属性,占了几百字节。

于是又补了两条规则:先整块删 <sodipodi:xxx/> 自闭合元素,再删成对出现的 <sodipodi:xxx>...</sodipodi:xxx>。

这提醒了一件事:正则处理 XML 时,属性和元素是两个维度,很容易只想到一个。

精度:全局替换的副作用​

把小数位从 6 位压到 2 位,通常能省 10%–20%。但直接对全文跑一条 \d+\.\d+ 的正则,会把不该动的东西也改掉,比如 version="1.1" 变成 version="1"。

这类属性对渲染没影响,但语义变了。更稳的做法是只处理几何相关属性(d、cx、cy、r、x、y、width、height、transform),代价是要解析标签结构,代码会长不少。

我目前选了「全局替换」这条捷径,并在界面上把精度做成可选项(0–4 位),让用户自己判断。这是明确的取舍,不是疏忽。

顺带一句:精度设成 0 时,圆会变成多边形,插画边角会明显折线。图标一般 1–2 位就够了。

实测效果​

拿一个带注释、metadata、namedview 的 120×120 测试图标:

原始 853 B
优化后 285 B (-67%)

验证方式是:输出的字符串仍以 <svg 开头、xlink 命名空间保留、id 和引用完好,再用浏览器渲染预览对照 —— 不是只看体积变小就完事。

什么时候别用这类工具​

如果 SVG 里嵌了栅格图(<image> base64),或者用了大量 <text>,优化收益会很有限,而误改的风险更高。这种文件更适合手工整理,而不是丢进工具一把梭。

加载评论中...