无论缓存控制标头如何,Chrome 都不会缓存 Webpack 动态导入的 javascript 块;火狐缓存

问题描述

我的主页中有一个入口包,它在 DOMContentLoaded 之后使用 import() 动态导入一个沉重的 JS 块。

在网络选项卡中查看 DevTools,我看到行为完全符合预期:在 DOMContentLoaded 之后,发出一个新请求来加载该单独的块。

但是,我注意到虽然所有其他块(初始同步块,立即加载)都被正确缓存(它们的状态是灰色的 200,大小为 memory_cache),但动态导入的块总是被服务器请求,更糟糕的是,它以 200 状态重新下载,即使它的内容没有改变。

enter image description here

这在 Firefox 中根本不会发生;动态导入也会被缓存。

enter image description here

所有动态导入都会发生这种情况,无论页面或条目包如何。

在 Chrome 中检查那些动态导入资产的响应标头,您可以清楚地看到它应该被缓存:

cache-control: max-age=315360000
cache-control: public
content-encoding: gzip
content-length: 210215
content-type: application/javascript
date: Sat,15 May 2021 19:33:45 GMT
expires: Thu,31 Dec 2037 23:55:55 GMT
last-modified: Sat,15 May 2021 19:32:27 GMT
pragma: public
server: Nginx
vary: Accept-Encoding

这是一个带有 Webpack 5 gem 设置的 Rails 6,因此所有包都从 /packs/ 提供。这是 Nginx 配置:

location ~ ^/(assets|packs|images|javascripts|stylesheets|swfs|system|uploads|blog-media)/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    add_header Pragma public;
    add_header ETag "";
    break;
  }
  • 我的 Chrome 开发工具中没有选择“禁用缓存”;
  • 最后修改的响应头稳定(它没有改变);
  • 文件名是稳定的(不会改变);
  • 内容长度没有改变;
  • 我已使用 diffchecker.com 逐行比较正在缓存的块的 REQUEST 和 RESPONSE 标头以及未缓存的动态块...实际上没有区别,但对于明显的 {{1} } 和 path 字段;

还需要注意的是,在 Firefox 中,如果我使用 CMD R 重新加载页面,它会自动content-length 添加到请求标头中,但这会使 Nginx 返回 {{1 }} 对于所有块(因此,请求命中服务器并出现在 Nginx 日志中,但由于 304 响应而没有下载任何内容,并且 Cache-Control max-age=0 出现在传输的列中。但是如果我单击我的徽标(充当导航到主页),然后我看到 200 状态,304 在transfered 列中,并且没有请求命中Nginx。一切都符合预期。

然而,Chrome 的行为完全不同。 CMD R 不会添加in cache 标头,因此所有块(动态导入除外)在大小列中返回 200 和 in cache。这些不会影响 Nginx。但是,动态导入请求不仅命中 Nginx,而且 Nginx 返回 200 状态,强制下载,所以我不明白为什么 Nginx 再次发送资产(200)而不是 304 响应就像 Firefox 一样。

我尽可能自定义 Nginx 日志以将 cache-control max-age 0 添加输出中,但对于动态导入它是空的; (如上所述,当我重新加载页面时,我可以看到 Firefox 的 (memory cache))。

更新 这太奇怪了,它是随机发生的。每大约 5 次使用 CMD+R 重新加载一次,动态块也会按预期显示为缓存:

enter image description here

也许我遇到了 Chrome 错误? (Chrome 版本 90.0.4430.212),因为 Firefox 按预期工作?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)