type
Post
status
Published
date
Jan 2, 2025
slug
svg-cache
summary
SVG图标通过SVG雪碧图的方式加载,浏览器会缓存请求,影响页面性能和用户体验。刷新缓存的方法包括重新打开页面、页面跳转、修改地址或设置缓存时间。最佳方案是手动调整SVG文件的缓存时间以平衡服务器性能和用户体验。
tags
前端
svg
html
浏览器
category
技术分享
icon
password
😀
调研图标库的搭建过程中,发现bootstrap的SVG图标库加载的方式很特殊,使用一种SVG雪碧图的方式(SVG Sprite File),在学习的过程中也发现了一个很奇怪的现象。

1️⃣ 基本原理

根据getbootstrapgetbootstrapBootstrap 图标库中的代码,这样就实现了一个简单的SVG图标的加载。浏览器会自动请求(相对路径):bootstrap-icons.svg 下的资源,拿到的资源如下:
可以看到返回的就是一个个被 symbol 标签包裹的SVG片段, 之后 <use href="bootstrap-icons.svg#basket" /> 会从中匹配出 idbasket 的SVG片段并以 shadow root 的方式嵌入在页面中,这样就完成了一次SVG的渲染。

2️⃣ 雪碧图的网络请求

这里比较奇怪的是,use 标签中 href 属性的请求不会在调试面板的 network 看板中出现,整个过程似乎是在浏览器中进行。
  1. 不支持跨域请求
    1. notion image
      如果将 usehref 的地址更换为跨域地址,则会出现以上报错,可见该属性并不支持跨域请求。
  1. 存在缓存
    1. 在这里我使用自己的Express server 代理 bootstrap-icons.svg 文件的请求,仅第一次访问页面时会打印该接口的日志:
      之后哪怕修改 bootstrap-icons.svg 中的内容,再重新reload页面甚至重启服务,都是不会再重新请求的, 不同页面之前相同 href 的缓存并不共享

3️⃣ 刷新缓存

可见SVG渲染中的缓存的可控性非常重要, 因为这不仅影响到页面性能,也会影响到用户体验。如果缓存机制处理不当,可能会导致用户看到过期的图标,或者增加不必要的网络请求。
测试下来,刷新缓存的方案有如下几种:
  1. 关掉当前页面,重新打开新的tab时(并非每次都会生效)
  1. 页面跳转 eg: 从A跳B,B会刷新缓存
  1. 修改 href 中的地址
  1. ‼️ 修改SVG文件的缓存时间 res.setHeader("Cache-Control", "no-cache");
 

4️⃣ 总结

总结下来,可控性最好的方法是4,实际使用过程中可以根据自己的方案手动调整过期时间,在服务器性能和用户体验间找到更好的平衡。