由于 2022 年 5 月以来 jsdelivr 访问进一步受限,对于仍需要使用 jsdelivr 的站长而言,自建反向代理服务是最优选择。为了在服务端和客户端都实现加速,我们采用 nginx 的缓存机制,初次请求之后不需回源;同时,使静态资源在浏览器中缓存时间更长。此外,由于涉及到跨域资源共享(CORS)问题,还需要在响应头中配置Access-Control-Allow-Origin关键字,以实现域名白名单机制,并保证资源在浏览器中正常加载。

1. 完整配置文件

配置文件: jsdelivr.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
proxy_cache_path /var/www/jsdelivr.cache levels=2:2 use_temp_path=off keys_zone=jsdelivr:50m inactive=180d max_size=500m;

server
{
listen 443 ssl;
server_name jsdelivr.example.com; # 替换成你的域名

# ssl 证书配置
ssl_certificate 你的证书;
ssl_certificate_key 你的证书私钥;
ssl_trusted_certificate 你的证书链;

# ssl 连接配置
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
server_tokens off;
fastcgi_param HTTPS on;
fastcgi_param HTTP_SCHEME https;

# 日志配置
access_log /usr/local/nginx/logs/jsdelivr.log;

location / # 此部分配置解读见下一节
{
proxy_pass https://cdn.jsdelivr.net;
proxy_ssl_server_name on;
proxy_set_header Host cdn.jsdelivr.net;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_http_version 1.1;
proxy_set_header Connection "";
add_header X-Cache $upstream_cache_status;
proxy_ignore_headers Set-Cookie Cache-Control expires;
proxy_cache jsdelivr;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 180d;
expires 180d;
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "https://blog.example.com";
}
}

将该文件保存为jsdelivr.conf,再在nginx.confhttp块中包含(include)该文件即可。

2. 配置文件解读

2.1 缓存文件配置

使用proxy_cache_path指令进行缓存文件配置:

proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size];

该指令中:

  • path 为缓存文件存放路径;
  • levels 为缓存文件目录的层次结构,levels=2:2 表示两级目录都使用 2 位 16 进制数命名;
  • use_temp_path 表示临时文件是否直接存放于缓存目录中,如果该值为off,则临时文件将直接放在缓存目录中;反之,则需要用proxy_temp_path设置一个目录。为了减少不必要的拷贝,建议设为off
  • keys_zone 表示在共享内存中设置的存储区域名称和大小。该存储区用来存放缓存的 key 字符串,keys_zone=jsdelivr:50m表示该区域的名称为 jsdelivr,大小为 50m,这样 nginx 可以快速判断一个 request 是否命中缓存,1m 可以存储 8000 个 key,10m 可以存储 80000 个 key;
  • inactive 表示未被访问文件在缓存中保留时间;
  • max_size 为最大缓存空间,如果不指定,会使用掉所有磁盘空间。当达到配额后,会删除最少使用的 cache 文件。

2.2 反向代理配置

在反向代理配置中,我们需要实现以下功能或特性:

  1. 将请求转发到https://cdn.jsdelivr.net
  2. 缓存状态码为200的请求,时限180天
  3. 设置跨域资源共享(CORS)策略,允许来自https://blog.example.com的请求
  4. 设置资源在浏览器中缓存时间为180天

在location块中,如下指令分别实现了以上功能:

  1. 请求转发
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 将流量转发到https://cdn.jsdelivr.net
    proxy_pass https://cdn.jsdelivr.net;
    # 因采用https,所以需要使用SNI指明主机名
    proxy_ssl_server_name on;
    # 设置请求头主机名
    proxy_set_header Host cdn.jsdelivr.net;
    # 记录代理信息
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    # 设置HTTP协议,并建立长连接
    proxy_http_version 1.1;
    proxy_set_header Connection "";
  2. 服务端缓存设置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # X-Cache表明请求是否命中缓存
    add_header X-Cache $upstream_cache_status;
    # 禁用源站的cookie和浏览器缓存设置
    proxy_ignore_headers Set-Cookie Cache-Control expires;
    # 设置缓存的key_zone名称,必须与proxy_cache_path中的设置一致
    proxy_cache jsdelivr;
    # 设置缓存的key名称
    proxy_cache_key $host$uri$is_args$args;
    # 设置缓存的条件,只缓存状态码200的请求,缓存时限为180天
    proxy_cache_valid 200 180d;
  3. CORS设置
    1
    2
    3
    4
    # 禁用源站的Access-Control-Allow-Origin请求头
    proxy_hide_header Access-Control-Allow-Origin;
    # 自定义Access-Control-Allow-Origin请求头,注意包含协议和域名
    add_header Access-Control-Allow-Origin "https://blog.example.com";
  4. 客户端缓存设置
    1
    2
    # 设置缓存的失效日期为180天
    expires 180d;

3 参见

  1. 分享一个nginx反代jsdelivr的优化配置

  2. Nginx 内容缓存及常见参数配置

  3. Module ngx_http_proxy_module