Nuxt.js部署GAE后缓存HTML导致JS文件404问题求助
问题说明
在Google App Engine上部署开启SSR的Nuxt.js静态站点时,更新生产版本后总会出现JS文件404的情况。排查后发现是HTML页面被过度缓存,每次请求都返回304,导致页面还在引用旧构建生成的、已经不存在的JS文件。但同样的代码在普通Docker容器里部署就没这个问题,更新后HTML会直接返回200,用户不用手动清缓存也能正常访问。
我当前的配置基本跟着Nuxt官方文档走,只移除了和Cloudflare SSL冲突的secure配置:
现有配置
app.yaml
runtime: nodejs16 handlers: - url: /_nuxt static_dir: dist/_nuxt - url: /(.*\.(gif|png|jpg|ico|txt))$ static_files: static/\1 upload: static/.*\.(gif|png|jpg|ico|txt)$ - url: /.* script: auto automatic_scaling: min_idle_instances: 1 min_instances: 1
nuxt.config.js
{ ssr: true, target: 'static' }
package.json脚本
{ "scripts": { "dev": "nuxt", "build": "nuxt build && nuxt generate", "gcp-build": "nuxt build && nuxt generate", "start": "nuxt start", "generate": "nuxt generate" } }
之前试过把HTML文件设为静态文件处理,但引发了一堆问题:非尾部斜杠的URL会被强制重定向到带斜杠的,站点地图访问不了,规范URL全指向根路径“/”,只能放弃这个方案。另外可以排除Cloudflare的问题,因为用Google自带的appspot.com域名也会出现同样的异常。
解决办法
1. 调整app.yaml的缓存控制规则
核心是给不同类型的资源设置差异化的缓存策略:带哈希的静态资源可以永久缓存,而HTML页面强制不缓存,确保每次请求都拿最新的。修改后的app.yaml handlers部分如下:
handlers: - url: /_nuxt static_dir: dist/_nuxt # Nuxt生成的静态资源带内容哈希,设置永久缓存 headers: Cache-Control: "public, max-age=31536000, immutable" - url: /(.*\.(gif|png|jpg|ico|txt))$ static_files: static/\1 upload: static/.*\.(gif|png|jpg|ico|txt)$ headers: Cache-Control: "public, max-age=31536000" - url: /.* script: auto # 强制禁止浏览器和GAE缓存HTML页面 headers: Cache-Control: "no-cache, no-store, must-revalidate" Pragma: "no-cache" Expires: "0"
这样设置后,用户每次访问页面都会获取最新的HTML,自然会引用新构建的JS文件;而静态资源因为文件名带哈希,更新后不会和旧文件冲突,永久缓存也不会有问题。
2. 确认Nuxt资源引用的正确性
检查dist目录下生成的HTML文件,确保里面的script标签引用的是带哈希的JS文件(比如/_nuxt/xxxx.abc123.js),这是Nuxt默认的行为,只要构建过程没出错就没问题。
3. 部署时用新版本号强制更新
部署新版本时,用gcloud app deploy --version=vxxx指定新的版本号,GAE会启动新实例逐步替换旧实例,避免旧实例缓存的内容影响用户访问。
补充:为什么Docker里没这个问题?
Docker部署时一般用Nginx之类的web服务器提供静态文件,默认对HTML的缓存策略比较宽松,不会强制缓存;而GAE的script: auto模式默认对动态返回的HTML有缓存设置,才导致了这个差异。
内容的提问来源于stack exchange,提问作者llessa

