小东西。花太长。favicon,小图标在浏览器标签,是这个整个网站最小资产而它战我比反向代理更硬。
它应该是什么
标签图标这里是一个小的BMK手迹用一个山字形图纹卡进它,匹配标题的锁定。我没有手绘它作为一个光栅图像,我构建它作为一个HTML瓦(static/_favicon-tile.html)使用真实供应商Literata字体和真实网站颜色,然后用Playwright呈现它到PNG所以字形真的使用同样排版如网站其余而不是某个回退系统字体一个SVG<text>元素会有默默代替。两个大小得到生成,32px对于标签和512px对于想要一个更大的图标(主屏幕快捷方式,那种事情),加上一个apple-touch-icon在180px。
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png?v=2" />
<link rel="icon" type="image/png" sizes="512x512" href="/favicon-512.png?v=2" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=2" />注意?v=2在每一个的末尾。那不在原始。那是伤组织来自这整个故事。
第一轮:它只是没有更新
我在设计中途重新画了favicon,重新生成PNG,部署,刷新页面。旧图标。仍然旧山形在标签。我假设我弄了构建,检查文件在磁盘上,新字节在那里对,正确像素,正确文件,正确路径。浏览器只是不再要求它。
出来favicons是一个资产类型浏览器用某东西接近宗教的虔诚缓存,而且大多数忽略正常的缓存控制头你会用在别的东西上破缓存。Chrome特别历史上缓存了一个网站的favicon长时间独立于服务器说什么,有时需要历史和缓存清除完全,有时需要一个实际URL改变,不只是新字节在同样URL。一个平刷新不会摸它。或者重新加载用缓存在devtools禁用,这是事情我尝试第二和这通常固定完全这个类问题。
第二轮:责备错的层
在我弄清楚它是浏览器之前,我花了一段时间怀疑容器,因为这个栈运行在Docker后面而我已经被过时构建层烧过(一个实际不同的漏洞早在这个项目涉及node_modules得到缍砸在Docker构建因为我还没有写一个.dockerignore还)。所以我首先下去那个路径:用--no-cache重建前端图像,确认新PNG字节坐在frontend/build/client/favicon-32.png在运行容器内,卷起容器自己的端口URL绕过Caddy全部。新字节,每次,直接从源。服务器所有的时间在做它的工作正确。它从来没有是容器。这纯粹在我自己浏览器的favicon缓存里,几层远离任何一个部署可以摸。
那是部分那实际花的时间:排除我自己的基础结构在我接受漏洞住在某地我有零控制上之前。
修复
你不能告诉一个浏览器的favicon缓存失效。什么你可以做的是停止问同样的URL。所有的东西我在弄清楚之前尝试保持同样的URL:
<!-- 之前:同样的URL每次,浏览器从来不为它再问 -->
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />一个查询字符串在href的末尾使它一个不同的资源就缓存关心,尽管它解决到磁盘上完全同样的文件:
<!-- 之后 -->
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png?v=2" />?v=2是整个修复。下一次我改变favicon艺术为真,那变成?v=3,等等。它是同样的技巧作为缓存破坏一个CSS或JS束用一个内容哈希,只是这里手工完成自从一个favicon是这样罕见编辑那整个构建工具管道为它感觉像过度杀伤。一个数字,手动撞,每次像素实际上改变。
什么我会告诉过去的我
检查容易的、哑的、尴尬的解释在有趣之前。"浏览器只是在一个小PNG上是固执的"是一个无聊答案而我想要漏洞是什么东西更技术上满足的,某个Docker层缓存微妙我可以为写一个更聪明的修复。它不是。这是一个五个字符的查询字符串我可以已经添加在前十分钟如果我有信了无聊的解释而不是追逐容器大约半小时首先。
事情那让它更差在它变得更好之前
部分为什么我怀疑自己在浏览器缓存理论那么长是我首先在一个隐私窗口测试它,想那会排除浏览器缓存完全,新资料,没有历史,肯定没有favicon缓存也不。错误的新图标显示那里也第一次,这感觉像固体证据它一点都不是一个缓存问题。什么我没有实现直到更后是Chrome的favicon缓存不是严格地与浏览资料的正常缓存相同的或历史,它更接近一个分离的、更长时间存在的商店键更多在URL本身,而且一个私人窗口不可靠地开始那个一个空的或者。所以我的控制测试不是实际上为控制东西我想它是,而且它送我进一步下去容器责备路径比证据应该有。
有也一个更小的、无聊的原因构建侧真正应得了第一看:同样的favicon PNG存在复制到一些不同的构建输出位置一次,frontend/build/client/,SvelteKit开发输出在.svelte-kit/output/client/下,而源static/目录他们都来自。三个同样的两个文件的复制横跨一个正常构建是完全那种东西那去陈旧在一个点并不另一个如果一个构建步骤得到跳过,所以排除"错副本得到服务"不是偏执狂,它只是不是这个时间实际漏洞住。
我也想只重新命名文件完全,favicon-32-v2.png而不是撞一个查询字符串,什么保证一个缓存错失零歧义。决定反对它,自从那意味着更新每一个参考到旧文件名横跨app.html和其他任何地方它的链接,对比接触一个数字在一个地方。查询字符串做同样的工作为一个更小的分数的编辑。