Skip to content

前端使用 Nginx 部署项目——从零开始 ​

本文档专为零基础初学者编写,从最基础的概念讲起。 每个步骤都有详细说明、注意事项和常见错误提醒。

目录 ​

  1. Nginx 是什么?(大白话解释)
  2. 学 Nginx 之前需要知道的基础知识
  3. 准备工作:你需要什么?
  4. Linux 基础命令(够用就行)
  5. 连接你的服务器(SSH)
  6. 安装 Nginx
  7. 第一个 Nginx 配置文件
  8. 部署你的前端项目
  9. 理解核心配置项
  10. SPA 单页应用的 history 路由配置
  11. 安全配置:开启 HTTPS
  12. Nginx 的日志与排错
  13. 常见问题与踩坑(初学者版)
  14. 完整配置模板
  15. 进一步学习建议

1. Nginx 是什么?(大白话解释) ​

Nginx(发音 "engine-x")是一个 Web 服务器软件。 通俗地说,它的工作就是:当用户在浏览器输入你的网址,Nginx 负责把网站的文件(HTML、CSS、JS、图片)通过网络发给用户的浏览器。

你可以把 Nginx 理解为"你家网站的大门口":

  • 客人来了 -> Nginx 开门迎接(响应 HTTP 请求)
  • 客人要商品 -> Nginx 去货架找(返回静态文件)
  • 商品需要从仓库调 -> Nginx 去联系仓库(反向代理到后端)
  • 客人太多 -> Nginx 维持秩序(高并发处理)
  • 想装个防盗门 -> Nginx 配置 HTTPS

Nginx 不是编程语言,不是框架。它是一个服务器软件,就像 Chrome 是"浏览器软件"一样。 作为前端开发者,你要做的就是:安装它、告诉它你的前端文件在哪里、怎么处理不同的访问请求。

2. 学 Nginx 之前需要知道的基础知识 ​

2.1 什么是服务器? ​

服务器就是一台 24 小时开机的电脑,放在机房或者云上(阿里云、腾讯云)。 你的前端项目文件就放在这台电脑上。Nginx 安装在这台电脑上,负责把文件发给访问者。

2.2 什么是 IP 地址和域名? ​

  • IP 地址:服务器的门牌号,如 123.45.67.89
  • 域名:好记的名字,如 www.example.com
  • DNS:电话本,告诉浏览器某个域名对应哪个 IP

你可以不用域名,直接用 IP 地址访问。但生产环境通常需要域名(因为 HTTPS 证书需要域名)。

2.3 什么是端口? ​

端口是服务器上的"门",不同程序走不同的门:

2.4 什么是前后端分离? ​

前后端分离的架构中,Nginx 扮演"中间人"的角色: 浏览器请求 -> Nginx -> 如果是静态文件,直接返回 -> 如果是 API 请求,转发给后端服务器 -> 后端处理完,Nginx 把结果返回浏览器

2.5 常用术语速查表 ​

术语大白话解释
Web 服务器存放网站文件并提供网络访问的软件
反向代理浏览器请求 Nginx,Nginx 再去请求后端,再返回结果
静态文件不会变化的文件:HTML、CSS、JS、图片
负载均衡有多个后端时,Nginx 把请求分发给不同后端
SSL/TLS加密协议,让 HTTP 变成 HTTPS

3. 准备工作:你需要什么? ​

3.1 必备清单 ​

项目说明费用参考
一台云服务器阿里云/腾讯云/华为云的轻量应用服务器约 50-100 元/月
SSH 连接工具用来远程操作服务器免费
一个域名(可选)如 example.com约 30-60 元/年
你的前端项目写好的 Vue/React 项目已有

3.2 购买云服务器后要做的第一件事 ​

登录云服务商的控制台,找到"安全组"或"防火墙",添加入站规则:

  • 端口 80(HTTP):允许所有人访问
  • 端口 443(HTTPS):允许所有人访问
  • 端口 22(SSH):允许你连接(默认已有)

安全组是新手最容易忽略的配置!很多人装好 Nginx 后打不开网页,就是因为安全组没放行 80 端口。

3.3 什么是 SSH? ​

SSH 是"安全外壳协议",用来从你的电脑远程连接到服务器的命令行界面。 连接上之后,你就可以在命令行操作服务器,就像坐在它面前一样。

4. Linux 基础命令(够用就行) ​

你不需要成为 Linux 专家,以下命令足够完成 Nginx 相关操作:

bash
pwd           # 查看当前目录路径
ls -la        # 列出当前目录所有文件(包含隐藏文件)
cd /var/www/  # 切换到指定目录
cd ..         # 返回上级目录

cat file.txt    # 查看文件内容
nano file.txt   # 编辑文件(初学者友好)

cp source.txt dest.txt        # 复制文件
mv old.txt new.txt            # 重命名/移动
rm file.txt                   # 删除文件
mkdir mydir                   # 创建目录

sudo chmod 755 file           # 修改权限
sudo chown www-data:www-data /var/www/myapp  # 修改所有者

# 查看 Nginx 相关进程
ps aux | grep nginx

# 查看日志
tail -f /var/log/nginx/error.log

强烈建议初学者先用 nano 编辑文件。它比 vim 直观得多,界面底部有快捷键提示。

5. 连接你的服务器(SSH) ​

Windows 系统 ​

bash
# 打开 Terminal 或 PowerShell,输入:
ssh root@你的服务器IP
# 例如:ssh root@123.45.67.89
# 然后输入密码(输入时不会显示),回车
# 看到 root@your-server:~# 就表示连接成功了

macOS / Linux 系统 ​

bash
ssh root@你的服务器IP

常见连接问题 ​

  • 第一次连接会出现 "Are you sure?" 提示,输入 yes 回车
  • 连接不上?检查:
    1. 服务器是否开机
    2. IP 地址是否正确
    3. 安全组是否放行了 22 端口

6. 安装 Nginx ​

6.0 Nginx 的版本策略(先看懂再安装) ​

Nginx 开源版同时维护两条分支(依据 nginx.org 官方说明):

分支版本号规律更新节奏适合谁
mainline(主线版)中间数字为奇数,如 1.31.x约每 1-2 个月,含最新功能+安全修复官方推荐大多数生产环境使用
stable(稳定版)中间数字为偶数,如 1.30.x约每年一次大版本,只回移植关键修复对稳定性要求极严、不想跟新功能的环境

截至 2026 年中,主线为 1.31.x、稳定为 1.30.x(1.30.0 于 2026-04 发布,带来了 Early Hints、后端 HTTP/2、上游 sticky 会话等新特性)。⚠️ 注意:Linux 发行版自带的 apt/yum 源里的 Nginx 往往是落后一两个大版本的旧版(如 Ubuntu 仓库常见的 1.24.x),需要新特性或及时的安全补丁时,应改用 nginx.org 官方仓库安装。

6.1 Ubuntu/Debian 系统 ​

bash
# 第一步:更新软件包列表
sudo apt update

# 第二步:安装 Nginx
sudo apt install nginx -y

# 第三步:验证是否安装成功
nginx -v
# 例如显示:nginx version: nginx/1.24.0(发行版自带源的版本,
# 版本号取决于你的 Ubuntu 版本,不一定是最新版)

6.2 CentOS/RHEL 系统 ​

bash
sudo yum install nginx -y
nginx -v

6.3 启动 Nginx ​

bash
sudo systemctl start nginx      # 启动
sudo systemctl enable nginx     # 设置开机自启
sudo systemctl status nginx     # 查看状态

6.4 验证 Nginx 是否正常运行 ​

在浏览器地址栏输入你的服务器 IP 地址。 如果看到 "Welcome to nginx" 的页面,恭喜你,安装成功了!

如果浏览器提示"无法访问此网站":检查安全组是否放行了 80 端口。 如果看到的是其他内容:可能 80 端口已被其他程序占用。

7. 第一个 Nginx 配置文件 ​

7.1 Nginx 配置文件在哪? ​

bash
/etc/nginx/                     # Nginx 配置目录
/etc/nginx/nginx.conf          # 主配置文件
/etc/nginx/sites-available/    # 站点配置(可用)
/etc/nginx/sites-enabled/      # 站点配置(已启用)
/var/log/nginx/access.log      # 访问日志
/var/log/nginx/error.log       # 错误日志
/var/www/html/                 # 默认网站目录

7.2 创建你的第一个 HTML 文件 ​

bash
sudo mkdir -p /var/www/myapp
sudo nano /var/www/myapp/index.html

粘贴以下内容:

html
<!DOCTYPE html>
<html>
<head>
    <title>我的第一个 Nginx 网站</title>
</head>
<body>
    <h1>Hello World! Nginx 配置成功!</h1>
    <p>这是我的第一个 Nginx 网站。</p>
</body>
</html>

7.3 创建第一个 Nginx 配置 ​

bash
sudo nano /etc/nginx/sites-available/myapp

粘贴以下内容:

nginx
server {
    listen 80;
    server_name _;        # _ 表示匹配所有域名

    root /var/www/myapp;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

7.4 启用这个站点 ​

bash
# 创建软链接到 sites-enabled
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/

# 测试配置语法(每次修改后都要执行!)
sudo nginx -t
# 看到 "test is successful" 再继续

# 重载 Nginx 使配置生效
sudo systemctl reload nginx

7.5 验证 ​

在浏览器中访问你的服务器 IP,应该看到 "Hello World!" 页面。

如果页面没出来,按顺序排查:

  1. sudo systemctl status nginx # Nginx 在运行吗?
  2. sudo tail -f /var/log/nginx/error.log # 看错误日志
  3. ls -la /var/www/myapp/index.html # 文件存在吗?
  4. sudo chmod 755 /var/www/myapp # 权限对吗?

7.6 配置文件的组织结构:include 链 ​

你只往 sites-available 放了一个文件,Nginx 为什么就认识它?因为主配置是一层层 include 进来的(Debian/Ubuntu 打包的默认 nginx.conf):

/etc/nginx/nginx.conf                  # 主入口
 └── http {
      └── include /etc/nginx/conf.d/*.conf
      └── include /etc/nginx/sites-enabled/*   # ← 你的软链接在这里被加载
          }

sites-available(可用)和 sites-enabled(已启用)是 Debian 系发行版的打包约定,nginx 本身不认识这两个目录名,CentOS/RHEL 默认只用 conf.d/。所以给 CentOS 写教程的文章会让你把配置直接放 /etc/nginx/conf.d/myapp.conf——两者只是放文件的目录不同,内容写法完全一样。

常用命令行工具(比 systemctl 更直接,nginx -t 在 7.4 已见过):

bash
nginx -t          # 只检查配置语法与语义,不重启(务必熟记)
nginx -s reload   # 平滑重载配置(systemctl reload 底层就是它)
nginx -s stop     # 立即停止
nginx -s quit     # 处理完当前请求后优雅退出
nginx -V          # 查看编译参数:装了哪些模块、配置文件路径在哪

💡 nginx -t 为什么重要:reload 前 Nginx 会先解析新配置,如果解析失败,旧配置继续工作;但 stop + 错误配置会让服务彻底起不来。所以任何改动都先 -t 再 reload,这是 Nginx 运维的第一安全习惯。

8. 部署你的前端项目 ​

8.1 构建项目 ​

bash
# 在你本地电脑上执行
npm run build
# 构建完成后会生成 dist/ 目录
ls dist/
# index.html  assets/  favicon.ico

8.2 上传到服务器 ​

bash
# 方式一:scp(最简单)
scp -r dist/* root@你的服务器IP:/var/www/myapp/

# 方式二:rsync(推荐,只传改动过的文件)
rsync -avz --delete dist/ root@你的服务器IP:/var/www/myapp/

# 上传后修正权限(非常重要!)
sudo chown -R www-data:www-data /var/www/myapp/

8.3 更新 Nginx 配置指向你的项目 ​

nginx
server {
    listen 80;
    server_name your-domain.com;  # 换成你的域名或 IP

    root /var/www/myapp;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

注意这里 try_files 的最后一个参数从 =404 变成了 /index.html。 这是因为 SPA 应用需要把所有路径都指向 index.html,由前端路由来处理。

8.4 测试并重载 ​

bash
sudo nginx -t
sudo systemctl reload nginx

权限问题是新手最常遇到的坑。如果上传后页面显示 403 Forbidden,99% 是文件权限问题。 解决方案:chown -R www-data:www-data /var/www/myapp/

9. 理解核心配置项 ​

9.1 server 块 ​

每个 server 块定义一个"虚拟主机":

nginx
server {
    listen 80;                # 监听 80 端口
    server_name example.com;   # 这个域名来的请求才处理
    root /var/www/myapp;       # 网站文件目录
    index index.html;          # 默认首页文件名
}

9.2 location 块 ​

location 根据 URL 路径匹配不同的处理方式:

nginx
location / {
    # 所有请求都到这里
}

location /api/ {
    # API 请求转发到后端
    proxy_pass http://localhost:3000/;
}

location ~* \.(jpg|png|css|js)$ {
    # 正则匹配:图片、CSS、JS 文件
    expires 30d;
}

9.3 try_files——最重要的指令 ​

nginx
try_files $uri $uri/ /index.html;

# 访问 /user/123 时:
# 1. 查找 /var/www/myapp/user/123    -> 不存在
# 2. 查找 /var/www/myapp/user/123/   -> 不存在
# 3. 返回 /var/www/myapp/index.html  -> 前端路由处理

9.4 root vs alias ​

nginx
location /app/ {
    root /var/www;      # 实际路径:/var/www/app/
}

location /app/ {
    alias /var/www/;     # 实际路径:/var/www/
}

初学者建议统一用 root,alias 容易配错路径。 ⚠️ 内部机制:用 root 时,Nginx 把完整 URI 拼接到 root 后面(/app/x.js -> /var/www/app/x.js);用 alias 时,Nginx 把 location 前缀替换成 alias 的值。所以 alias 结尾要不要带 /、location 结尾要不要带 / 必须严格对应,否则就会出现文件名多一段/少一段的经典 404。

9.5 Gzip 压缩:静态站点提速第一课 ​

Nginx 的 ngx_http_gzip_module 是响应过滤器,官方文档称开启后"通常能把传输数据体积减少一半甚至更多"。前端产物(JS/CSS/HTML)文本占比极高,收益非常明显。

nginx
http {
    gzip on;                     # 默认是 off,必须显式开启
    gzip_min_length 1k;          # 默认 20 字节;小于 1k 的文件压缩收益抵不上 CPU 开销
    gzip_comp_level 5;           # 1-9,默认 1。5-6 是体积/CPU 的常见平衡点
    gzip_types text/css application/javascript application/json image/svg+xml;
                                 # text/html 无条件压缩,不用写进 types
    gzip_vary on;                # 输出 Vary: Accept-Encoding,帮 CDN 正确缓存
}
指令默认值说明
gzipoff总开关
gzip_comp_level1压缩级别 1-9,越高越省流量越费 CPU
gzip_min_length20低于此长度不压缩
gzip_typestext/html额外要压缩的 MIME 类型;* 匹配所有
gzip_varyoff是否添加 Vary: Accept-Encoding 响应头

⚠️ 两个官方文档明确提醒的点:① 图片/字体(woff2 等)本身已是压缩格式,不要加入 gzip_types;② HTTPS 下对"含敏感数据的动态响应"开启压缩存在 BREACH 攻击风险,纯静态资源无此顾虑,给登录接口等动态响应加 gzip off 即可。

💡 更进一步:前端构建工具(Vite 的 vite-plugin-compression、Webpack 的 compression-webpack-plugin)可以在构建时直接生成 .gz 文件,Nginx 用 gzip_static on 直接发送预制文件,零运行时 CPU 开销(需 --with-http_gzip_static_module,发行版包一般已编译)。

9.6 反向代理必配的请求头 ​

第 8/10 章的 location /api/ { proxy_pass ... } 只是"能转发",要让后端拿到真实信息,还需要一组 proxy_set_header:

nginx
location /api/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;                        # 让后端看到原始域名,而不是 127.0.0.1:8080
    proxy_set_header X-Real-IP $remote_addr;            # 客户端真实 IP
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 完整代理链 IP 列表
    proxy_set_header X-Forwarded-Proto $scheme;         # 客户端用的是 http 还是 https
}

为什么需要:经过代理后,后端看到的 TCP 对端永远是 Nginx 自己。不传 X-Forwarded-For,后端日志里所有用户的 IP 都是 127.0.0.1;不传 X-Forwarded-Proto,后端生成的重定向/链接可能错用 http scheme。Express 的 app.set('trust proxy', ...) 等框架开关就是专门消费这些头的。

💡 proxy_pass 末尾有没有 / 决定 URI 处理方式(内部机制):

  • proxy_pass http://127.0.0.1:8080;(不带 URI)→ 原始 URI 完整透传:/api/user 到后端仍是 /api/user
  • proxy_pass http://127.0.0.1:8080/;(带 /)→ 剥掉 location 前缀:/api/user 变成 /user 这就是第 9.2 节示例里 proxy_pass 带 / 的含义——后端接口本身不挂在 /api 前缀下时,靠它做前缀剥离。

10. SPA 单页应用的 history 路由配置 ​

10.1 为什么要特别配置? ​

Vue Router 或 React Router 的 history 模式下:

  • 页面内跳转:/ -> /user -> /about,没问题
  • 直接访问 /user/123 或 F5 刷新:Nginx 找 /user/123 文件 -> 找不到 -> 404

10.2 标准解决方案 ​

nginx
server {
    listen 80;
    server_name example.com;
    root /var/www/myapp;
    index index.html;

    # 核心:所有非文件路径都指向 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源长期缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # API 转发
    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
    }
}

注意:nginx 按“最长前缀匹配”选择 location。location /api/ 比 location / 更长,所以 /api 请求会自动命中 location /api/,与书写顺序无关(只有正则 location ~ 才按书写顺序匹配,第一个命中的生效)。

10.3 子路径部署 ​

如果网站部署在子路径(如 /app/):

nginx
server {
    listen 80;
    server_name example.com;

    location /app/ {
        alias /var/www/myapp/;
        try_files $uri $uri/ /app/index.html;
    }
}

同时在前端项目设置:

  • Vue 3:vite.config.ts 中 base: "/app/"
  • React:package.json 中 "homepage": "/app/"

10.4 静态资源缓存的内部机制:expires 与 add_header 怎么配合 ​

浏览器缓存分两档(对应 HTTP 协议的两代机制):

档位响应头行为适用
强缓存Cache-Control: public, max-age=31536000有效期内不发请求,直接用本地副本带 hash 的 JS/CSS/图片
协商缓存Last-Modified / ETag发请求问服务器"变了吗",没变返回 304(不传 body)Nginx 对静态文件自动支持,默认开启

Nginx 里 expires 1y; 会同时改写 Expires 和 Cache-Control 两个头(官方 ngx_http_headers_module 的行为);add_header Cache-Control "public, immutable" 则是原样追加头字段。三个注意事项:

  1. ⚠️ add_header 的继承陷阱:add_header 只写进本层的定义就"断根"——如果 location / 里写了一个 add_header,server/http 层的所有 add_header 在这个 location 就全部失效。这是"配了安全头却不生效"的头号原因(Nginx 官方文档说明 add_header 从当前层级继承,一旦本层出现 add_header 就不再向上继承)。
  2. ⚠️ 只对特定状态码生效:expires / add_header 默认只响应 200、201、204、206、301、302、303、304、307、308;想对 4xx/5xx 也加头,要写 add_header X-Frame-Options "DENY" always;。
  3. 💡 immutable 是告诉浏览器"有效期内连 F5 强刷都不发条件请求",只配带内容 hash 的文件名(如 index-a1b2c3.js);index.html 永远不能加强缓存,否则每次发版用户都要手动清缓存才能看到新页面(对应第 13 章问题 5)。

11. 安全配置:开启 HTTPS ​

11.1 为什么要用 HTTPS? ​

  • 浏览器标记"不安全"影响用户信任
  • 用户数据(密码、支付信息)在传输中加密
  • 很多新特性(如 Service Worker)需要 HTTPS

11.2 使用 Certbot 自动配置(推荐初学者使用) ​

bash
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx

# 获取证书并自动配置 Nginx
sudo certbot --nginx -d example.com -d www.example.com
# 按提示输入邮箱、同意协议
# 完成后访问 https://example.com 就有 HTTPS 了

# 测试自动续期是否正常
sudo certbot renew --dry-run

如果没有域名,不能用 HTTPS(Let's Encrypt 需要域名验证)。 Certbot 会自动修改你的 Nginx 配置并设置定时续期任务,你不需要手动操作。

12. Nginx 的日志与排错 ​

12.1 日志文件位置 ​

bash
/var/log/nginx/access.log   # 谁访问了什么(调式用)
/var/log/nginx/error.log    # 错误信息(排查问题用)

12.2 查看日志 ​

bash
# 查看最新的几条错误
tail -f /var/log/nginx/error.log

# 查看访问日志
tail -f /var/log/nginx/access.log

# 查看特定时间段的日志
grep "2026/06/11" /var/log/nginx/error.log

12.3 排错基本流程 ​

页面打不开?
  |
  +-- 浏览器提示"无法访问"          -> 检查安全组 80 端口
  |
  +-- 浏览器显示 403 Forbidden     -> 文件权限问题,chown www-data
  |
  +-- 浏览器显示 404 Not Found     -> 检查 try_files + 文件路径
  |
  +-- 浏览器显示 502 Bad Gateway   -> 后端没启动或连不上
  |
  +-- 页面显示旧内容              -> 浏览器缓存,配置 HTML 不缓存

12.4 读懂一行 access.log ​

默认 combined 格式的一行长这样:

123.45.67.89 - - [01/Sep/2026:10:00:00 +0800] "GET /assets/index-a1b2c3.js HTTP/2.0" 200 45678 "https://example.com/" "Mozilla/5.0 ..."
字段含义排错用法
$remote_addr客户端 IP有代理时这里可能是 CDN/SLB 的 IP(见 9.6 的 X-Forwarded-For)
请求行方法 + URI + 协议看到 HTTP/1.0 往往是探针/扫描器
状态码HTTP 响应码499 表示客户端等不及主动断开(Nginx 特有码),后端慢时会大量出现
$body_bytes_sent响应体字节数配合 gzip 对比体积
Referer / User-Agent来源页 / 浏览器定位爬虫、盗链

💡 自定义日志还能加"性能字段"定位慢请求:log_format perf '$remote_addr [$time_local] "$request" $status $request_time $upstream_response_time' 然后在 access_log 里引用 format=perf。$request_time 是请求总耗时(秒,含网络传输),$upstream_response_time 是后端处理耗时——两者差距大说明问题在带宽/客户端,接近说明问题在后端(变量含义以 nginx.org ngx_http_log_module 文档为准)。

13. 常见问题与踩坑(初学者版) ​

问题 1:访问 IP 显示"无法访问此网站" ​

原因:安全组(防火墙)没放行 80 端口 解决:登录云服务商控制台,添加入站规则:端口 80,来源 0.0.0.0/0

问题 2:显示 403 Forbidden ​

原因:Nginx 用户(www-data)没有文件权限 解决:

bash
sudo chown -R www-data:www-data /var/www/myapp/
sudo chmod -R 755 /var/www/myapp/

问题 3:点击链接正常,刷新就 404 ​

原因:SPA 的 history 路由没配 try_files 解决:在 location / 中添加 try_files $uri $uri/ /index.html;

问题 4:修改配置后网站全打不开了 ​

原因:配置语法错误,Nginx 重载失败 解决:

bash
sudo nginx -t        # 看具体错误在哪一行
# 修正后重新
sudo nginx -t
sudo systemctl reload nginx

问题 5:部署新版本后用户还是旧页面 ​

原因:浏览器缓存了 HTML 文件 解决:让 HTML 不缓存,JS/CSS 用 hash 文件名:

nginx
location / {
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    try_files $uri $uri/ /index.html;
}

问题 6:API 代理一切正常,WebSocket 连不上 ​

原因:proxy_pass 默认用 HTTP/1.0 且不透传 Upgrade 握手头,WebSocket 握手(Connection: Upgrade / Upgrade: websocket)直接被 Nginx 丢弃,表现为连接不断 1006 断开。 解决(三行缺一不可,见 nginx.org ngx_http_proxy_module 文档):

nginx
location /ws/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;                  # 默认 1.0,不支持 keep-alive/Upgrade
    proxy_set_header Upgrade $http_upgrade;  # 透传客户端的 Upgrade 头
    proxy_set_header Connection "upgrade";   # 完成协议切换握手
    proxy_read_timeout 3600s;                # 空闲连接别被默认 60s 超时掐断
}

问题 7:上传大图片/附件报错,Nginx 直接返回 413 ​

原因:client_max_body_size 默认 1m,超过就拒收,请求根本到不了后端。 解决:

nginx
client_max_body_size 20m;   # 放在 http/server/location 层均可

14. 完整配置模板 ​

nginx
# HTTP -> HTTPS 跳转
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    # SSL 证书
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/myapp;
    index index.html;

    # API 转发
    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
    }

    # SPA 路由
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

⚠️ 关于模板里的 listen 443 ssl http2;:从 Nginx 1.25.1 起,listen 参数形式的 http2 已被标记为过时(obsolete),官方推荐的现代写法是拆开写——listen 443 ssl; 另起一行 http2 on;(见 nginx.org ngx_http_v2_module 文档的示例配置)。老写法在 1.29/1.30/1.31 上仍可用,但新项目建议用新写法。 💡 想再快一步:在 443 的 server 块里加 listen 443 ssl quic; + http3 on;(1.25.1 引入 HTTP/3 支持,需证书与 UDP 443 放行),并在 http 块开启第 9.5 节的 gzip。

15. 进一步学习建议 ​

你已经学会的 ​

  • Nginx 是什么、能做什么
  • 购买和连接云服务器
  • 安装和启动 Nginx
  • 创建 Nginx 配置
  • 部署前端项目
  • 配置 SPA history 路由
  • 开启 HTTPS
  • 查看日志和排查问题

接下来可以学的 ​

  1. Gzip 压缩——减小文件体积,加快加载速度
  2. 反向代理——转发 API 请求到后端
  3. 缓存策略——浏览器缓存 + Nginx 缓存
  4. 负载均衡——多个后端分担压力
  5. WebSocket——实时通信配置
  6. 性能调优——worker 数量、连接数等

最重要的三句话 ​

  1. root 指向你的前端文件目录
  2. try_files 解决 SPA 刷新 404
  3. 每次改配置先 nginx -t,再 reload

记住这三句话,你已经可以完成 90% 的前端部署工作了。

基于 VitePress 构建的个人学习文档知识库