【Web 应用缓存与部署优化指南】

发布于:2025-06-13 ⋅ 阅读:(21) ⋅ 点赞:(0)

Web 应用缓存与部署优化指南

目录

  1. HTTP 缓存机制
  2. 浏览器缓存体系
  3. Cache Storage API
  4. 构建与部署优化
  5. 环境特定策略
  6. 问题诊断与解决方案

HTTP 缓存机制

强缓存

浏览器直接使用本地缓存,不与服务器通信。

控制头部

Cache-Control: max-age=31536000
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: must-revalidate
Expires: Wed, 12 Jun 2026 12:00:00 GMT

特点

  • 命中强缓存时不发送请求
  • 通过 DevTools 可见 200 (from disk cache)200 (from memory cache)
  • 适用于带版本号的静态资源

协商缓存

浏览器与服务器协商验证资源是否更新。

控制头部

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 12 Jun 2024 12:00:00 GMT
If-Modified-Since: Wed, 12 Jun 2024 12:00:00 GMT

特点

  • 每次都发送请求验证
  • 资源未变时返回 304 状态码
  • 适用于 HTML 等经常变化的资源

浏览器缓存体系

缓存位置

  1. Service Worker Cache
  2. Memory Cache
  3. Disk Cache
  4. Push Cache (HTTP/2)

缓存优先级

  1. Service Worker 的 Cache Storage
  2. Memory Cache(内存缓存)
  3. Disk Cache(磁盘缓存)
  4. 网络请求

Cache Storage API

基本概念

Cache Storage API 是现代浏览器提供的可编程缓存接口。

使用场景

  • Service Worker 中
  • Window 上下文(普通网页)
  • Worker 上下文

权限与安全

  1. 访问限制

    • 仅能访问同源的 Cache Storage
    • 无法访问浏览器的 HTTP 缓存
    • 无法访问其他存储机制
  2. 控制台访问

    • 可以在 DevTools 中查看和操作
    • 仅限当前网站的缓存
    • 遵循同源策略

基本用法

// 打开缓存
const cache = await caches.open('v1');

// 存储响应
await cache.put('/api/data', response);

// 读取缓存
const cached = await cache.match('/api/data');

// 删除缓存
await cache.delete('/api/data');

// 清理所有缓存
const keys = await caches.keys();
await Promise.all(keys.map(key => caches.delete(key)));

构建与部署优化

1. Webpack 配置优化

module.exports = {
  output: {
    filename: '[name].[contenthash:8].js',
    chunkFilename: '[name].[contenthash:8].chunk.js',
    clean: true  // 清理 dist 目录
  },
  optimization: {
    moduleIds: 'deterministic',  // 确保模块 ID 稳定
    runtimeChunk: 'single',      // 分离 runtime 代码
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      }
    }
  }
}

2. 服务器配置

# HTML - 协商缓存
location / {
    try_files $uri $uri/ /index.html;
    add_header Cache-Control "no-cache";
    etag on;
}

# 静态资源 - 长期缓存
location /static/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# 动态 chunks - 长期缓存
location /chunks/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

3. 版本控制系统

// webpack 注入版本信息
new webpack.DefinePlugin({
    'process.env.APP_VERSION': JSON.stringify(require('./package.json').version),
    'process.env.BUILD_TIME': JSON.stringify(new Date().toISOString())
})

class VersionManager {
    async checkUpdate() {
        const response = await fetch('/version.json', {
            headers: { 'Cache-Control': 'no-cache' }
        });
        const { version, buildTime } = await response.json();
        
        if (version !== process.env.APP_VERSION || 
            buildTime !== process.env.BUILD_TIME) {
            await this.handleUpdate();
        }
    }

    async handleUpdate() {
        await this.clearCaches();
        if (confirm('发现新版本,是否刷新?')) {
            window.location.reload(true);
        }
    }
}

4. 部署流程

#!/bin/bash
VERSION=$(date +%Y%m%d%H%M%S)
DEPLOY_DIR="/usr/share/nginx/html"

# 1. 新建版本目录
mkdir -p ${DEPLOY_DIR}/${VERSION}

# 2. 部署新文件
cp -r dist/* ${DEPLOY_DIR}/${VERSION}/

# 3. 切换版本
ln -sfn ${DEPLOY_DIR}/${VERSION} ${DEPLOY_DIR}/current

# 4. 保留最近版本
ls -dt ${DEPLOY_DIR}/20* | tail -n +4 | xargs rm -rf

环境特定策略

开发环境

# 开发环境配置
location / {
    add_header Cache-Control "no-store";
    add_header Pragma no-cache;
}

特点

  • 禁用缓存
  • 启用热更新
  • 频繁版本检查

测试环境

# 测试环境配置
location / {
    add_header Cache-Control "no-cache";
    etag on;
    if_modified_since exact;
}

特点

  • 短期缓存
  • 版本检测
  • 强制刷新功能

生产环境

策略

  • HTML:协商缓存
  • JS/CSS:contenthash + 长期缓存
  • 图片/字体:hash + 长期缓存
  • API:按数据特性决定

问题诊断与解决方案

1. 缓存不一致

症状

  • 新旧代码混合
  • 功能异常
  • 样式错乱

解决方案

  1. 确保资源使用 contenthash
  2. 实施"先静态资源,后 HTML"的部署顺序
  3. 实现版本检测机制

2. CDN 缓存问题

症状

  • 不同地区用户体验不一致
  • 更新不同步

解决方案

  1. 使用版本化 URL
  2. 配置合适的缓存刷新策略
  3. 实施灰度发布

3. 测试环境缓存

症状

  • 测试结果不准确
  • 需要频繁强制刷新

解决方案

  1. 配置 no-store 头部
  2. 使用版本检测
  3. 提供一键刷新功能

最佳实践总结

1. 资源分类策略

  • HTML:协商缓存
  • JS/CSS:contenthash + 长期缓存
  • 图片/字体:hash + 长期缓存
  • API:按数据时效性决定

2. 构建优化

  • 使用 contenthash
  • 合理代码分割
  • 提取公共依赖

3. 部署流程

  • 版本化部署
  • 支持快速回滚
  • 自动化发布

4. 监控维护

  • 监控缓存命中率
  • 观察版本更新效果
  • 及时处理缓存问题

记住:缓存策略不仅是技术选择,更是产品需求、用户体验和运维效率的平衡。好的缓存策略应该:

  • 保证资源更新的及时性
  • 最大化缓存利用率
  • 支持快速问题诊断
  • 便于运维和回滚