飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

答案:HTTP缓存机制

问题: 空少(前端)给飞翔官网的app.js设置了Cache-Control: max-age=86400(1天)。第二天他紧急修复了一个线上bug并重新部署,但用户反馈问题依然存在。请分析原因,并给出更好的缓存策略方案。

答案:

原因分析

星宇(运维工程师)和图妹(测试工程师)一起排查后发现,问题的根源在于浏览器缓存。

当空少设置Cache-Control: max-age=86400后,浏览器会将app.js缓存到本地,并在1天内直接从本地缓存读取,不再向服务器发起请求。即使用户第二天访问官网,浏览器发现缓存尚未过期(距离上次请求不到86400秒),就直接使用本地旧版本的app.js,导致bug修复没有生效。

# 第一次请求响应头
HTTP/1.1 200 OK
Content-Type: application/javascript
Cache-Control: max-age=86400
Last-Modified: Mon, 09 Jun 2026 08:00:00 GMT

# 第二天浏览器直接使用本地缓存,不发请求到服务器

更好的缓存策略方案

雁姐(技术经理)召集空少和鸣哥(DevOps)讨论后,制定了以下分层缓存策略:

方案一:文件名加哈希(推荐)

在构建阶段为静态资源文件名添加内容哈希,如app.a3f7b2c.js。当代码变更时,哈希值改变,URL也随之改变,浏览器会将其视为全新资源。

<!-- 构建前 -->
<script src="/app.js"></script>

<!-- 构建后(哈希自动更新) -->
<script src="/app.a3f7b2c.js"></script>

配合长期缓存:

# Nginx配置
location ~* \.(js|css|png|jpg)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

immutable表示资源在有效期内绝对不会改变,浏览器可以放心缓存一整年。

方案二:HTML不缓存,资源长期缓存

让入口HTML文件不缓存或短期缓存,HTML中引用带哈希的资源。这样只需更新HTML就能让客户端加载新资源。

# HTML响应头:不缓存或短期缓存
Cache-Control: no-cache

# 静态资源响应头:长期缓存
Cache-Control: public, max-age=31536000

方案三:使用版本号查询参数(简单但不够优雅)

<script src="/app.js?v=2"></script>

这种方式简单,但某些CDN或代理服务器可能不会将不同查询参数视为不同缓存键,存在风险。

飞翔公司最终方案

空少采用了Webpack构建 + 文件名哈希 + Nginx长期缓存的组合方案:

// webpack.config.js
module.exports = {
  output: {
    filename: '[name].[contenthash:8].js',
    chunkFilename: '[name].[contenthash:8].chunk.js',
  },
};
# /etc/nginx/conf.d/feixiang.conf
server {
    listen 80;
    server_name www.feixiang.net;
    
    location / {
        root /var/www/feixiang;
        index index.html;
        add_header Cache-Control "no-cache";
    }
    
    location ~* \.[a-f0-9]{8}\.(js|css)$ {
        root /var/www/feixiang;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }
}

这样,每次部署新版本时,哈希文件名自动更新,用户必定获取最新代码;同时静态资源可以享受一年的长期缓存,大幅提升重复访问速度。