静态网站版本平滑切换需符号链接与缓存策略协同:用current软链接切换版本目录,html设短缓存(如10s)确保实时更新,js/css等哈希资源设长缓存+immutable避免混搭,发布时ln -sf原子切换,旧版保留支持回滚与缓存自然过期。

静态网站的版本平滑切换,关键不是等缓存过期,而是让缓存行为和文件部署机制协同工作。符号链接负责“切版本”,缓存策略负责“控可见”——两者配合,才能避免用户加载到 HTML 新、JS 旧的混搭状态。
用符号链接隔离版本,Nginx 指向 current
把每次构建产物放进带版本号的独立目录,例如:
- /var/www/site/v1.2.3/(含 index.html、app.a1b2c3.js、style.d4e5f6.css)
- /var/www/site/v1.2.4/(新构建结果)
- /var/www/site/current → /var/www/site/v1.2.3(软链接)
Nginx 的 root 直接指向这个链接:
location / {<br> root /var/www/site/current;<br> index index.html;<br> try_files $uri $uri/ =404;<br>}
这样 Nginx 实际读取的是链接所指目录,且自动解析软链接,无需额外配置。
缓存策略按资源类型差异化设置
不同文件承担不同角色,缓存时间必须区别对待:
-
HTML 文件(index.html 等入口)设极短缓存:如
expires 10s;或add_header Cache-Control "no-cache, must-revalidate";。确保用户每次刷新都向 Nginx 发起新请求,由 Nginx 决定返回哪个版本的 HTML。 -
JS/CSS/图片等带哈希名的资源设长缓存 + immutable:如
add_header Cache-Control "public, max-age=31536000, immutable";。哈希已保证内容唯一性,immutable 可防止浏览器对带查询参数的请求误判为新资源,也避免强制刷新仍走本地缓存。
这样,HTML 快速更新,而它引用的资源因哈希不同天然不冲突,不会出现新版 HTML 加载旧版 JS 的问题。
发布时原子切换,缓存自然收敛
新版本构建完成并验证无误后,执行:
ln -sf /var/www/site/v1.2.4 /var/www/site/current
该操作是原子的,无中间态。所有后续请求立即看到 v1.2.4 下的 HTML;而浏览器中已缓存的 v1.2.3 的 JS/CSS 仍可正常加载(因为哈希不同,URL 完全独立),直到用户下次访问新 HTML 后触发新资源下载。
旧版本目录(v1.2.3)保留在磁盘上,既支持秒级回滚,也给浏览器缓存留出自然过期窗口,无需主动 purge 或通知 CDN。
补充建议:加一层兜底与可观测性
可在 location 块中添加简单日志,记录当前服务的版本路径:
log_format version_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$document_root"';<br>access_log /var/log/nginx/site-access.log version_log;
同时,在发布脚本中校验新目录是否包含关键文件(如 index.html 和主 JS),失败则中止 ln 命令,防止空链接导致大面积 404。











