Cache-Control 调错记录
谨记,TIL。
不久前更新本 Blog 代码,将所用的图标字体升级到最新版,顺便设置了 CSS font-display: block; 本意是避免显示图标的 ligatures。
后来发现仍然会有『图标延迟显示,导致界面布局产生位移』的现象,尤其在后台管理的 tabs 那片。
看来 block 没什么用,那么原因是什么呢?
无论用什么 font-display,首先得先下载这个字体的文件。总是有延迟,说明文件总是被重新请求(服务器/网络延迟),而不是读取浏览器本地的缓存文件。
字体、CSS、脚本等静态文件要做缓存,属于常识,我当然也做了相关配置,pcman 还提供了亚马逊的 CloudFront CDN。
检查浏览器的网络请求,看字体文件的 response header:嗯,X-Cahe: miss from cloudfront,CDN 没起作用;再看还有 Cache-Control: public, max-age=0, max-age=31536000
啥?虽然我并不怎么熟悉 cache-control 这东西,但是同一个变量 2 个值?!显然是不对的。
max-age 用于提示该资源可以被缓存的最长时间,0 当然是不缓存,每次都重新请求,第二个 31536000 是一年的秒数,是我在服务器端设置的。
ChatGPT 懂个球,这种问题还是需要 google。答案很少,SO 上有人说两个 max-age 首先是格式错误,客户端当然可以忽略并自己选择一个值,看来 CloudFront 选择了 0。
于是怀疑服务器设置。因为我的设置是通过 .htaccess 文件添加的,Apache 本身可能有设置来 override 我的。
禁用了我的 .htaccess,再看请求,还是老样子……不过第二个 max-age 现在是另一个值了——说明服务器果然有默认设置。
联系 DreamHost 的客服,回复很快,是的,DH 的 Apache 默认有 Cache-Control 设置,然后应我要求关闭了。
启用 .htaccess 再看,晕,还是 2 个值!我的值回来了,那个 0 依然存在。还有那个 public,我并没设置过这个值。
看来不是 Apache 的问题?
Debugging 时的一个技巧就是搜索错误信息本身,我于是加引号搜索 "cache-control: public, max-age=0, max-age=",翻到不会有人看的第二页结果,发现了一模一样的代码,在著名的 Express 项目的文档里。
顿时有了方向:Blog 程序所用的框架是 FoalTS,它本身的 HTTP 服务器就是基于 Express。而所有静态文件实际上是用的 FoalTS 的一个 serve static 的功能,该功能本质上也是调用 express.static() 这个中间件。
查阅了 express 的文档,果然,static() 的参数中就有 maxAge,默认值为 0,那个 public 也来自这里。
总算是找到原因了。时间不早该睡了,要是年轻 10 岁我就继续熬夜纠错……
最后的解决办法挺难看,反正就是设置参数让 Express 不要附加 cache-control,原理很简单,但是 FoalTS 没有直接提供可以加参数的地方,workaround 了一番,也向作者提交了一个 feature request。
本次调错的心得就是:多怀疑问题出在自己一方。当时有点急,还打扰了 pc 一番……DH 的客服估计也比较郁闷。
现在好了,缓存全面给力,CloudFront 也一片 Hit。希望 Blog 的速度感觉更快!
不不不,完全没打扰到我,我这里是白天时间。提供几个CloudFront CDN的文档参数说明而已。
看到问题解决太棒了,Amazon的Leadship principal之一的DIVE DEEP!
虽然我没看懂是什么原因导致的问题,但是大体能看到一个比较明确的思路。最近我在使用cloudflare的works搭建节点,期间也遇到过很多问题,但也差不多都克服了。
很高兴看到你能解决问题,我也在努力学习,你也是个很好的榜样
上传图片不可以了么? 现在选upload会报错。
是的,这个功能现在还没法用,努力开发中……
先另外找个图床?
ChatGPT 懂个球,这种问题还是需要 google。答案很少,
---
这类问题,推荐Google Bard。
看了你这篇文章,赶紧跑去优化了一下服务器上的Cache。
其实ChatGPT是比我懂得多的,虽然有时候答案未必是我想要的,但是给个思路还是问题不大的。
就继续放你的webhosting就好了,只要存储空间够,访问时候前边带着CloudFront CDN,效果不会太差。
单独的图床,还不如用AWS S3,最后AWS S3前边还是要加AWS CloudFront CDN做加速。
当然另一个思路,如果GCP Cloud Storage和Azure Blob Storage有免费的羊毛可以撸,那就用起来。