⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

10.4.4 图片如何加速访问——静态资源:缓存策略与 CDN 集成

静态资源不走应用服务器,Nginx 直接返回最快。

静态资源分类

类型示例缓存策略
带 hash 的文件main.abc123.js永久缓存
不带 hash 的文件logo.png短期缓存
HTML 文件index.html不缓存/短期

Nginx 静态资源配置

基础配置

nginx
server {
    listen 80;
    server_name www.example.com;
    
    # Next.js 静态资源
    location /_next/static/ {
        alias /var/www/app/.next/static/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # 公共资源
    location /public/ {
        alias /var/www/app/public/;
        expires 7d;
    }
    
    # 其他请求代理到应用
    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

缓存控制头

nginx
# 永久缓存(带 hash 的文件)
location ~* \.(js|css)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# 中期缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
    expires 30d;
    add_header Cache-Control "public";
}

# 短期缓存
location ~* \.(html|json)$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

Gzip 压缩

nginx
http {
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types 
        text/plain 
        text/css 
        text/javascript 
        application/javascript 
        application/json 
        application/xml
        image/svg+xml;
}
配置作用
gzip on启用压缩
gzip_vary添加 Vary: Accept-Encoding
gzip_min_length最小压缩大小
gzip_types压缩的 MIME 类型

CDN 集成

CDN 原理

配置 CDN 回源

  1. 在云服务商创建 CDN 加速域名(如 cdn.example.com
  2. 配置回源地址为 origin.example.com
  3. 在 Nginx 配置回源域名:
nginx
server {
    listen 80;
    server_name origin.example.com;
    
    location / {
        root /var/www/static;
        expires 1y;
    }
}

前端使用 CDN

javascript
// next.config.js
module.exports = {
  assetPrefix: process.env.NODE_ENV === 'production' 
    ? 'https://cdn.example.com' 
    : '',
}

对象存储 + CDN

将静态资源存储到 OSS/COS,通过 CDN 加速:

优势

对比项服务器存储OSS + CDN
存储成本
扩容需要升级磁盘自动
访问速度受服务器带宽限制全国节点加速
可用性依赖服务器99.99%+

上传到 OSS 示例

typescript
// NestJS 上传服务
import * as OSS from 'ali-oss';

const client = new OSS({
  region: 'oss-cn-hangzhou',
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: 'my-bucket',
});

async function uploadFile(file: Express.Multer.File) {
  const result = await client.put(`uploads/${file.originalname}`, file.buffer);
  return result.url;  // 返回 CDN 地址
}

缓存策略最佳实践

Next.js 静态资源

nginx
# _next/static 目录下的文件都带有 hash,可以永久缓存
location /_next/static/ {
    alias /var/www/.next/static/;
    expires max;
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# _next/image 图片优化
location /_next/image {
    proxy_pass http://127.0.0.1:3000;
    proxy_cache_valid 200 60m;
}

版本化资源

html
<!-- 带版本号的资源引用 -->
<link rel="stylesheet" href="/css/style.css?v=1.0.0">
<script src="/js/app.js?v=1.0.0"></script>

监控与调优

查看缓存命中率

nginx
# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;

缓存状态值

状态含义
HIT缓存命中
MISS缓存未命中
EXPIRED缓存已过期
BYPASS跳过缓存

常见问题

问题原因解决方案
资源更新后用户看不到浏览器缓存使用文件名 hash
CDN 不更新CDN 缓存未刷新手动刷新 CDN 缓存
图片加载慢图片太大压缩图片、使用 WebP
CORS 错误CDN 未配置跨域添加 Access-Control-Allow-Origin