有没有人觉得 http 缓存设计的很不合理?

2022-01-24 10:25:17 +08:00
 3dwelcome

一般来说,WEB 是一个 html 主页面,里面包含若干个 css/js 。正常 html 是不缓存,确保浏览器每次访问都是最新的内容(服务器返回 200 或者 304)。

而 css/js 是时间策略缓存,也就是没过期之间(由 max-age 来定),浏览器压根不会向服务器发任何请求!就算 JS 代码有更新,短时间内用户也无法感知。

为了破除这个限制,webpack 都会在 js/css 后面加上 hash ,来解决这个问题。

那么问题来了,为什么 HTTP 不设计成,能一次性的向服务器请求 HTML 里所有 css/js 的最后更新时间( last-modified-time ),看看有哪些文件变动了,再针对性的获取呢? 这样 JS 就不用每次都改新文件名了。

5157 次点击
所在节点    前端开发
57 条回复
ryd994
2022-01-25 10:12:27 +08:00
@3dwelcome 1. CSS 的 URI 是不是 HTML 的一部分?
如何你设置 max-age 为最长时间,那么浏览器不需要再发请求 revalidate 。也就实现了你的目的。

你建议 script src='file.js' last-modifed-time='utctime
这和 script src='utctime/file.js'
有什么区别?

你还可以使用 stale-while-revalidate ,浏览器会立刻使用 cache ,即使 cache 已经过期。然后再在后台和服务器更新。
ryd994
2022-01-25 10:12:56 +08:00
*如果 你设置 max-age 为最长时间
ryd994
2022-01-25 10:22:54 +08:00
而且你还可以使用 immutable
3dwelcome
2022-01-25 11:02:18 +08:00
@ryd994 “你建议 script src='file.js' last-modifed-time='utctime
这和 script src='utctime/file.js'
有什么区别?”

上面一句浏览器可以本地缓存比对,如果文件缓存里有,就不需要发一条 URL 请求去服务器。
下面一句浏览器必须去访问一下服务器,哪怕返回的是 304 。

“如果 你设置 max-age 为最长时间”
就是设置 max-age 才会导致这种不合理的情况发生,在 max-age 没到期前,浏览器默认就是 CSS/JS 有效的,和服务器不同步。
ryd994
2022-01-25 13:42:09 +08:00
@3dwelcome 1. “上面一句浏览器可以本地缓存比对,如果文件缓存里有,就不需要发一条 URL 请求去服务器。”这本就是浏览器的不正确实现。标准最初定义的是 max-age 过期前不必 revalidate 。但是由于各大浏览器都是这样实现,所以最终标准妥协了,变成了 max-age 前需要 revalidate 。

所以,后来加入了两个 cache-control 选项:
stale-while-revalidate ,浏览器立刻使用 cache ,但在后台 revalidate
immutable ,浏览器彻底相信 max-age ,max-age 前完全不 revalidate

如果你在 utctime/file.js 上使用这两个选项之一,就不会有你说的问题。
3dwelcome
2022-01-25 13:59:02 +08:00
@ryd994 你还是没理解我的意思,我是说 revalidate 就完全没有存在的必要!

如果 HTML 文件里有 JS 的 hash 值,那么问题就很简单。

* hash 和缓存一样,那浏览器获取了 HTML 后,就无需发起任何后续的网络连接。
* hash 和缓存不一样,那浏览器就直接去取最新的 JS 。

这样逻辑就清晰多了。浏览器去问服务器,某某 JS 文件要不要更新,本身就是一件多余的操作。
3dwelcome
2022-01-25 14:26:40 +08:00
@NewYear 我用 Chrome 实测没测出来。

官方没任何文档说 integrity 和浏览器本地缓存有什么必然联系。可能只和第三方 CDN 刷新机制有关系。

Chrome 下不匹配 integrity ,就是直接阻止脚本运行,弹出 The resource has been blocked 。

至于缓存没任何区别。
NewYear
2022-01-25 16:44:13 +08:00
@3dwelcome

我不知道你怎么测试的,我实测 Chomre 97.0.4692.99 正式版,是会形成缓存。单个页面单个 script 标签,第一次打开后会下载 js 文件,切换成别的 URL ,不改 integrity ,再访问不会产生新的通讯。

抓包软件上看得清清楚楚,明明白白。

我已经表达得很清楚了,你还在疯狂的反驳,测试数据也不正确,自写 JS 也不干(明明很简单就能实现完全可控的方式),不要回复我了,帮你搜索,帮你测试,最后还是无效沟通,这个贴浪费我太多时间了,再见。
ryd994
2022-01-25 17:35:44 +08:00
@3dwelcome 你看到我说的 immutable 选项了吗?你喜欢你可以把你所有静态资源设置 immutable ,然后把你的 hash 直接嵌在 URI 里。这样每个 URI 确实就是 immutable 的。

楼上的实测结果你也是完全没看,你如果认为 immutable 解决不了你的问题,拿出实测数据便是。

你真是好大的口气,明明是有现成的解决办法,你非要把之前的标准推翻用你的新标准。
为什么标准变成了现在这样,这不是你能决定的问题。你一直在以“如果互联网让我设计”为前提。然而互联网从一开始就不是谁设计,谁规定的。ietf 也只是参考性的记录。实际上是几个开路人说,诶,咱们就这么办。然后用的人多了,事实上就形成了通行的标准。
HTTP 缓存,不管最初的设计如何,各大浏览器用了这个标准,各大 Web 服务器用了这个标准,那这个标准就是标准。

如果你觉得你的标准可以推翻现有的标准,talk is cheap 。你需要有可用的代码实现,然后写一篇论文来证明你的标准,然后可以提交 rfc 。good luck
3dwelcome
2022-01-25 18:26:49 +08:00
@NewYear “我不知道你怎么测试的”

我用的是 chrome96, 不管改不改 integrity ,只要 max-age=0 ,资源过期了,浏览器就必定会向服务器发起新连接。

不是你说的,浏览器就直接不请求了。

这个测试结果是符合预期的。

integrity 改了,只会让你的资源加载失败,和网络缓存真没关系。不信你可以把相关的搜索资料给贴出来。
3dwelcome
2022-01-25 18:33:00 +08:00
@ryd994 你说的 immutable 就是彻底相信 max-age ,js 在有效期内是不会变的。

可是 js 内容改动是很正常的一件事情,为什么要去设置永恒不变呢?

这里讨论的是新思路,只要思路对了,用 JS 在 localStroage 里自己管理缓存,代码实现是很容易,回个贴不需要那么激动。
NewYear
2022-01-25 19:28:07 +08:00
最后申明,不要 @我了,我甚至连个程序员都不是,业余程序员都算不上,但是我遇到这个困扰的时候起码能找到 2-3 种解决办法。

给你最后一点建议,在你发挥超能力改变这个世界之前,请你先了解它,然后尝试一下有没有办法用起来,如果实在是不行,我真心的期待你有能力改变它。不管是钱也好、超能力也好、其他能力也好,我希望你有这个能力。

而你现在发起讨论,但又过于偏执,浪费的不光是你的时间,还有别人有限的生命,而且还是浪费在抬杠上面。


“只要 max-age=0 ,资源过期了”,这种参数确定不是为了抬杠而设计的吗?
3dwelcome
2022-01-25 20:06:50 +08:00
@NewYear 设置 max-age=0 肯定不是抬杠,如果大于 0 ,那么浏览器就自动默认资源在有效期内,是不会发起网络请求的。

这时候就算你把验证的 integrity 值给修改了,network 面板也不会有新的请求发起。

唯一变化就是资源认证不通过,加载失败。
ryd994
2022-01-26 01:46:07 +08:00
@3dwelcome 你的智商只能两句话看懂一句话,看完一句忘一句吗?
你自己提议加上 hash ,那把 hash 加到 URI 里之后,这个 URI 是不是就是 immutable 的?难不成你同一个 hash 还能变?

和你讨论真是浪费生命。


而你现在发起讨论,但又过于偏执,浪费的不光是你的时间,还有别人有限的生命,而且还是浪费在抬杠上面。
3dwelcome
2022-01-26 03:57:52 +08:00
@ryd994 "你自己提议加上 hash ,那把 hash 加到 URI 里之后"

我说的 hash 是指 ETAG ,是为了去通知浏览器让老资源过期,重新获取新资源。

和你说的“把 hash 加到 URI“完全是两回事。

我为什么要把资源设置成永恒不变呢?资源明明已经失效了!就想让浏览器把老资源给删了。
VagabondH
2022-01-27 17:21:33 +08:00
问题是 http 协议不负责 html 的解析,解析 html 的是浏览器
就因为 http 本身简单,才能这么大范围的使用,如果各种场景都适配优化,那它本身就太复杂了
VagabondH
2022-01-27 17:24:04 +08:00
我觉得你的标签上加 cache 属性的方案不但没有解决任何问题,还让缓存这个东西依赖上 script / link 标签了,变得更复杂了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/830203

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX