CDN 与缓存策略

14 阅读2分钟

引言

在现代前端开发中,性能优化是提升用户体验的关键环节。CDN(内容分发网络)和合理的缓存策略,能够显著减少资源加载时间,降低服务器压力,是前端性能优化的两大核心手段。本文将深入探讨 CDN 的工作原理、缓存策略的设计要点,以及如何在实际项目中应用这些技术。

一、CDN 基础原理

什么是 CDN

CDN(Content Delivery Network)是一种分布式的网络架构,通过将静态资源缓存到全球各地的边缘节点,让用户从距离最近的节点获取资源,从而降低延迟、提升访问速度。

CDN 工作流程

用户请求 → DNS 解析 → 选择最优节点 → 返回资源
              ↓
         节点有缓存?→ 直接返回
              ↓
         回源站获取 → 缓存到节点 → 返回给用户

常见 CDN 服务商

  • 国内:阿里云 CDN、腾讯云 CDN、网宿科技
  • 国际:Cloudflare、AWS CloudFront、Akamai

二、缓存策略核心概念

1. 浏览器缓存机制

浏览器缓存主要通过 HTTP 响应头来控制:

# 强缓存
Cache-Control: max-age=31536000, public
Expires: Wed, 21 Apr 2027 07:00:00 GMT

# 协商缓存
ETag: "33a64df551425fcc55e4d42a1459b3"
Last-Modified: Wed, 21 Apr 2026 07:00:00 GMT

2. Cache-Control 详解

Cache-Control 是最常用的缓存控制头,支持多个指令:

// 常见指令说明
max-age=31536000    // 缓存 1 年(秒)
public              // 可被任何缓存存储
private             // 仅用户浏览器可缓存
no-cache            // 使用前需验证
no-store            // 不缓存任何内容
must-revalidate     // 过期后必须验证

3. 强缓存 vs 协商缓存

类型特点适用场景
强缓存直接从本地读取,不请求服务器静态资源(JS、CSS、图片)
协商缓存向服务器验证是否过期动态内容、HTML 页面

三、实际代码示例

1. Nginx 缓存配置

server {
    listen 80;
    server_name example.com;
    
    # 静态资源 - 强缓存 1 年
    location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        # 添加版本号到文件名
        rewrite ^/(.*).[0-9a-f]{8}.(.*)$ /$1.$2 last;
    }
    
    # HTML 文件 - 协商缓存
    location ~* .html$ {
        expires -1;
        add_header Cache-Control "no-cache, must-revalidate";
    }
    
    # API 接口 - 不缓存
    location /api/ {
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }
}

2. 资源版本管理

通过文件名哈希实现长期缓存:

// Webpack 配置
module.exports = {
  output: {
    filename: '[name].[contenthash:8].js',
    chunkFilename: '[name].[contenthash:8].chunk.js'
  }
};

// Vite 配置
export default {
  build: {
    rollupOptions: {
      output: {
        entryFileNames: `[name].[hash].js`,
        chunkFileNames: `[name].[hash].js`,
        assetFileNames: `[name].[hash].[ext]`
      }
    }
  }
};

3. Service Worker 缓存

// sw.js
const CACHE_NAME = 'v1';
const urlsToCache = [
  '/',
  '/static/js/main.js',
  '/static/css/main.css',
  '/images/logo.png'
];

// 安装:缓存资源
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

// 拦截请求:优先从缓存读取
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response; // 返回缓存
        }
        return fetch(event.request)
          .then(response => {
            // 克隆响应并缓存
            const responseClone = response.clone();
            caches.open(CACHE_NAME)
              .then(cache => cache.put(event.request, responseClone));
            return response;
          });
      });
  );
});

四、CDN 最佳实践

1. 资源分类策略

// 资源分类缓存策略
const cacheStrategies = {
  // 核心资源 - 短缓存
  'index.html': { maxAge: 0, mustRevalidate: true },
  
  // 静态资源 - 长缓存 + 版本控制
  'js/*.js': { maxAge: 31536000, immutable: true },
  'css/*.css': { maxAge: 31536000, immutable: true },
  'images/*': { maxAge: 31536000, immutable: true },
  
  // API 数据 - 不缓存或短缓存
  'api/*': { maxAge: 0, noStore: true }
};

2. 缓存失效策略

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

<!-- 文件名包含哈希,内容变化时哈希改变 -->
<script src="/js/main.a1b2c3d4.js"></script>
<link rel="stylesheet" href="/css/style.e5f6g7h8.css">

方案二:查询参数

<script src="/js/main.js?v=20260422"></script>

方案三: CDN 刷新

# 阿里云 CDN 刷新接口
curl -X POST "https://cdn.aliyuncs.com/?Action=RefreshCdnObject&ObjectPath=https://example.com/js/main.js"

3. 性能优化技巧

// 预加载关键资源
<link rel="preload" href="/fonts/main.woff2" as="font">
<link rel="preload" href="/js/vendor.js" as="script">

// 预获取后续可能需要的资源
<link rel="prefetch" href="/js/page2.js">

// 资源提示
<link rel="dns-prefetch" href="https://api.example.com">
<link rel="preconnect" href="https://cdn.example.com">

五、监控与优化

1. 性能指标监控

// 使用 Performance API 监控资源加载
window.addEventListener('load', () => {
  const entries = performance.getEntriesByType('resource');
  entries.forEach(entry => {
    console.log(`${entry.name}: ${entry.duration}ms`);
  });
  
  // 计算资源加载时间
  const loadTime = performance.timing.loadEventEnd - 
                   performance.timing.navigationStart;
  console.log(`Total load time: ${loadTime}ms`);
});

2. 缓存命中率统计

// 通过响应头判断缓存状态
fetch('/api/data')
  .then(response => {
    const cacheStatus = response.headers.get('X-Cache');
    console.log(`Cache status: ${cacheStatus}`); // HIT or MISS
  });

总结

CDN 和缓存策略是前端性能优化的基石。通过合理配置:

  1. 静态资源使用强缓存 + 文件名哈希
  2. 动态内容使用协商缓存
  3. 关键资源使用预加载
  4. 持续监控缓存命中率和加载性能

记住:好的缓存策略 = 正确的 Cache-Control + 合理的资源版本管理 + 完善的失效机制。