我的博客是用 Hugo 生成的静态站点,生成之后就是一堆 HTML、CSS、JS 和图片文件。这种静态站点最适合用 Nginx 直接托管,速度快、配置简单、资源占用低。

这篇文章分享一下我目前用的 Nginx 配置,算是给静态博客的一个参考模板。

基础配置

最简单的静态博客配置只需要指定根目录和 index 文件:

 1server {
 2    listen 80;
 3    server_name blog.moxuan.xin;
 4    root /var/www/blog/public;
 5    index index.html;
 6    
 7    location / {
 8        try_files $uri $uri/ /index.html;
 9    }
10}

try_files $uri $uri/ /index.html 这个配置很重要,因为 Hugo 很多页面是干净的 URL,比如 /about/ 而不是 /about.html。如果直接访问目录找不到文件,就回退到 index.html

强制 HTTPS

现在 HTTP 基本已经被淘汰了,我直接把所有 80 端口的请求 301 跳转到 HTTPS:

 1server {
 2    listen 80;
 3    server_name blog.moxuan.xin;
 4    return 301 https://$server_name$request_uri;
 5}
 6
 7server {
 8    listen 443 ssl http2;
 9    server_name blog.moxuan.xin;
10    root /var/www/blog/public;
11    index index.html;
12    
13    ssl_certificate /etc/letsencrypt/live/blog.moxuan.xin/fullchain.pem;
14    ssl_certificate_key /etc/letsencrypt/live/blog.moxuan.xin/privkey.pem;
15    
16    location / {
17        try_files $uri $uri/ /index.html;
18    }
19}

http2 建议加上,能提升多资源并发加载的效率。

启用 Gzip 压缩

静态博客的 HTML、CSS、JS 都是文本,开启 Gzip 能大幅减少传输体积。在 http 块里加:

1gzip on;
2gzip_vary on;
3gzip_proxied any;
4gzip_comp_level 6;
5gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

gzip_comp_level 是压缩级别,1 最快但压缩率低,9 最慢但压缩率高。一般 6 是个不错的平衡点。

静态资源缓存

对于 CSS、JS、图片这些不常变化的文件,可以让浏览器和 CDN 缓存久一点:

1location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
2    expires 6M;
3    access_log off;
4    add_header Cache-Control "public, immutable";
5}

expires 6M 表示缓存 6 个月。如果以后更新了这些文件,可以通过改文件名(比如加 hash)来强制刷新。

图片懒加载配合

Nginx 本身不负责图片懒加载,这是前端的事情。但 Nginx 可以优化图片的传输方式。比如开启 sendfiletcp_nopush

1sendfile on;
2tcp_nopush on;
3tcp_nodelay on;

这些参数可以提升静态文件的发送效率。

安全相关 Header

顺手加一些安全响应头:

1add_header X-Frame-Options "SAMEORIGIN" always;
2add_header X-Content-Type-Options "nosniff" always;
3add_header Referrer-Policy "strict-origin-when-cross-origin" always;

这些不会直接影响性能,但能提升安全性。

配合 CDN 使用

如果博客流量比较大,建议前面套一个 CDN。我目前用的是 Cloudflare,配置好之后:

  1. DNS 解析到 Cloudflare。
  2. Cloudflare 回源到我的源站 Nginx。
  3. 静态资源被缓存到 Cloudflare 的边缘节点。

CDN 配置我单独写了一篇文章,这里就不展开了。

完整的配置示例

把上面的内容整合起来,我的完整配置大概是这样:

 1http {
 2    sendfile on;
 3    tcp_nopush on;
 4    tcp_nodelay on;
 5    keepalive_timeout 65;
 6    
 7    gzip on;
 8    gzip_vary on;
 9    gzip_proxied any;
10    gzip_comp_level 6;
11    gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
12    
13    server {
14        listen 80;
15        server_name blog.moxuan.xin;
16        return 301 https://$server_name$request_uri;
17    }
18    
19    server {
20        listen 443 ssl http2;
21        server_name blog.moxuan.xin;
22        root /var/www/blog/public;
23        index index.html;
24        
25        ssl_certificate /etc/letsencrypt/live/blog.moxuan.xin/fullchain.pem;
26        ssl_certificate_key /etc/letsencrypt/live/blog.moxuan.xin/privkey.pem;
27        
28        add_header X-Frame-Options "SAMEORIGIN" always;
29        add_header X-Content-Type-Options "nosniff" always;
30        
31        location / {
32            try_files $uri $uri/ /index.html;
33        }
34        
35        location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
36            expires 6M;
37            access_log off;
38            add_header Cache-Control "public, immutable";
39        }
40    }
41}

验证配置

每次改完 Nginx 配置,一定要先用 nginx -t 检查语法:

1nginx -t

没有报错再重载:

1nginx -s reload

总结

静态博客的 Nginx 配置不复杂,但有几个点做好了能明显提升体验:

  1. 强制 HTTPS,启用 HTTP/2。
  2. 开启 Gzip 压缩,减少传输体积。
  3. 静态资源长期缓存,配合 CDN 效果更佳。
  4. 加安全响应头,提升安全性。

如果你也用 Hugo、Hexo、Jekyll 这类静态生成器,这个配置基本可以直接拿去用,改改域名和路径就行。