有没有人觉得 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 就不用每次都改新文件名了。

4779 次点击
所在节点    前端开发
57 条回复
cmdOptionKana
2022-01-24 10:35:50 +08:00
可能因为最初 http 发明时每一个 byte 的流量、每一次 IO 都需要尽量节省吧。
NewYear
2022-01-24 10:55:02 +08:00
交流最好的方式是,不能只提问题,也要提解决方案。

虽然你给了解决方案,说白了也是不可行的,需要浏览器支持,需要服务器支持,难难难,而且你这个就涉及到所有软件都会面临的问题(自动升级)。。。你说的“一次性查询”,是怎么定义的,每天第一次?每次打开浏览器第一次?每次打开此网页的一次?如何定义呢。

就难度来说,JS 的开发者都有能力实现你所需要的这个功能,我举个例子,你服务器上可以有一个 json 的 list ,里面有每个 js 文件和日期,或者你用服务器语言自己定义一个动态的列表,浏览器有 localstorage (现在的浏览器没有不支持的)你也可以在里面放上一个 list ,然后在你任何想要“检查”的时候检查,然后版本号 /日期加入到 js 文件的 url 后面就可以了。

相对而言,是不是自己写的兼容性又高,又能满足自己的各种个性化需求呢?

不过说实话缓存这个东西确实是有点尴尬,我在服务器更新的 js 文件,大半年过去了,还能在同事电脑看到未修改前的版本,不过也是我没用心去处理,其实这些东西百度早有解决方案了。
micean
2022-01-24 10:59:49 +08:00
“一次性的向服务器请求 HTML 里所有 css/js 的最后更新时间”

那请求的策略是什么?
3dwelcome
2022-01-24 11:01:14 +08:00
@cmdOptionKana
@NewYear

我以为 HTTP2.0 比较新,会变一下方法,结果查了一下,缓存方面完全没有变。

js 加 hash 改名,其实就是变相破坏了浏览器原本的缓存策略。

html 有设计 JS 文件内容强校验属性《 script src='vue.js' integrity='sha-256:hash'》, 但就是没有 ETAG 缓存属性《 script etag='hash'》或者 Last-Modified 属性。
3dwelcome
2022-01-24 11:03:04 +08:00
@micean “那请求的策略是什么?”

只要在 HTML 里告诉浏览器,js 文件的最后修改时间,或者是最新的 HASH ,那样文件名不用改名,也能获取最新文件。
Biwood
2022-01-24 11:03:09 +08:00
这跟 html 、css 、js 没什么关系,而是 HTTP header 里的设置问题,你说的 webpack 加 hash ,那只是本地开发调试不方便配置 header 缓存策略,从而用最简单和原始的方法。凡是 html 能用的缓存策略,可以适用于任何经由 HTTP 传输的其他文件类型上面。
serge001
2022-01-24 11:05:24 +08:00
你上面说的方案不是已经很好了嘛:html 使用协商缓存(返回 200 或者 304 ),js ,css 使用强缓存(使用本地缓存),更新的时候更新 hash 即可,至于你说的:为什么 HTTP 不设计成,能一次性的向服务器请求 HTML 里所有 css/js 的最后更新时间( last-modified-time ),看看有哪些文件变动了,再针对性的获取呢?

从实现的难度和灵活性来讲并没有比使用 hash 好很多吧?
otakustay
2022-01-24 11:06:52 +08:00
HTTP2 下已经没有必要“一次性请求”这个事情了吧,反正都并发了,header 也有 HPack 压缩了。如果觉得需要 HTML 解析才能找到 JS/CSS 资源有个串行过程的话,用<link preload>,然后把 head 部分单独作为 chunk 吐出来,不要等 body 就行
3dwelcome
2022-01-24 11:09:53 +08:00
@serge001 比如 HTML 里有 10 个 JS 和 CSS ,服务器有变动了,明明可以在 HTML 里通知浏览器的。

只要设计有《 meta jsname='file.js' cache-control-etag='hash'》类似的语句就行。

总比浏览器自己去访问十次服务器,对比 10 次 HASH ,浪费流量来的好吧。
kop1989smurf
2022-01-24 11:13:54 +08:00
我觉得有两方面的原因。

主要原因是文件的“最后修改时间”变化,和文件重新读取并不是一个强逻辑关系。

次要是有历史原因。忘记这个术语叫什么了,大概意思是“同样参数的 get ,返回值要一样”。
mxT52CRuqR6o5
2022-01-24 11:13:56 +08:00
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified
有这个特性啊,你在 js/css 的 response 里声明不走强缓存,就可以走协商缓存了
micean
2022-01-24 11:13:57 +08:00
@3dwelcome

没区别啊,更新还是通过每次请求来判断。
不想改文件名,也必须要有其他方式做到“不同值”,显然 hash 文件名是性能最高的方式吧
浏览器做到最大限度的缓存,剩下的就交给 html 服务提供者自己了
mxT52CRuqR6o5
2022-01-24 11:16:00 +08:00
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
总不能你自己想要协商缓存不想要强缓存,就禁止 web 标准添加强缓存的特性,禁止所有人使用强缓存的 feature 吧
serge001
2022-01-24 11:17:01 +08:00
@3dwelcome “浏览器自己去访问十次服务器,对比 10 次 HASH” 这句不是很明白,css 和 js 的缓存策略通常都是配置为强缓存的,max-age 会设置一个很大的时间,避免去重新请求
3dwelcome
2022-01-24 11:18:22 +08:00
@mxT52CRuqR6o5 “有这个特性啊,你在 js/css 的 response 里声明不走强缓存,就可以走协商缓存了”

不走强缓存,那用户每次刷新一下主页,HTML 有十个 js/css 文件,HTTPS 就会连续去请求十次!

这在移动互联网时代,是很难接受的,没准哪个请求就卡住,拖慢了页面整体载入后腿。
wanguorui123
2022-01-24 11:20:53 +08:00
max-age 是减少请求,Etag 是避免获取重复文件相当于 Hash ,Cache 与 ETag 组合使用比较好
serge001
2022-01-24 11:21:27 +08:00
至于你说的方案,对于引入的第三方 js 怎么处理?难道要请求 html 的服务器去请求一下第三方的服务器获取这个 js 文件的更新时间嘛
mxT52CRuqR6o5
2022-01-24 11:22:27 +08:00
@3dwelcome 哦哦,没看清楚是要一次性是吧,那旧版 http 可能确实没法直接做到,不过不是还有 http2 吗,1 次和 10 次没多大区别了,http1 里搞这些可能难以避免 breaking change 吧
mxT52CRuqR6o5
2022-01-24 11:23:11 +08:00
http1 的话也许可以尝试在业务层自行实现一次性的向服务器请求 HTML 里所有 css/js 的最后更新时间
3dwelcome
2022-01-24 11:31:13 +08:00
@mxT52CRuqR6o5 “http1 的话也许可以尝试在业务层自行实现一次性的向服务器请求 HTML 里所有 css/js 的最后更新时间”

我确实是这样处理的,还是觉得麻烦。

直接修改 JS 文件嘛,如果不用 webpack ,每次还要用 ctrl+F5 刷新一下,真是累人。

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

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

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

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

© 2021 V2EX