从前端部署到请求转发:一篇搞懂 Nginx 是怎么把页面和接口路由起来的

摘要

最近在用 Jenkins 部署前后端服务时,我把后端 jar 包部署这条链路先跑通了,接着开始补前端部署这块。前端和后端最大的区别在于:后端通常是 java -jar 直接起服务,而前端大多数是打包成静态文件,再交给 Nginx 去提供访问。同时,Nginx 还常常承担接口转发、HTTPS、安全加固、资源压缩等职责。刚开始接触这些配置时,我最困惑的就是:location 到底是什么?aliasindextry_filesproxy_pass 分别在干什么?浏览器请求一个 Nginx 的 IP 地址后,它到底会被路由到哪里?这篇文章就把这些问题从实际部署的角度讲清楚。


一、为什么前端部署通常离不开 Nginx

如果是一个典型的前端项目,比如:

  • Vue
  • React
  • 普通静态站点

打包之后,产物通常是一堆静态文件,例如:

  • index.html
  • main.js
  • app.css
  • 图片、字体、SVG 等资源

这些文件本身并不会“自己跑起来”,它们需要一个 Web 服务器去提供访问。
而 Nginx 正好就很适合做这件事。

所以前端部署时,最常见的模式就是:

  1. Jenkins 或本地打包出 dist 或 zip 包
  2. 把打包产物放到目标服务器
  3. 由 Nginx 提供静态资源访问
  4. 再由 Nginx 把接口请求转发到后端服务

可以把它理解成:

  • 前端页面、JS、CSS 由 Nginx 直接返回
  • 后端接口 由 Nginx 转发给 Java 服务

二、一个最常见的实际场景

假设现在有这样一台服务器:

192.168.251.6

上面部署了:

前端

  • 项目名:qding-scc-front
  • 部署目录:/usr/share/nginx/html/qding-scc-front

后端

  • Java 服务监听端口:8162

我希望浏览器这样访问:

访问前端页面

http://192.168.251.6/qding-scc-front/

访问后端接口

http://192.168.251.6/api/qding/user/list

那这个时候,Nginx 就要负责判断:

  1. 这个请求是要找静态文件?
  2. 还是要转给后端接口?
  3. 如果请求的是前端单页应用路由,比如 /qding-scc-front/user/list,找不到真实文件时应该怎么办?

这就是 Nginx 配置真正解决的问题。


三、Nginx 在这个场景里扮演什么角色

可以先看一张时序图。

Java后端服务静态文件目录Nginx浏览器Java后端服务静态文件目录Nginx浏览器请求 http://192.168.251.6/qding-scc-front/查找 /usr/share/nginx/html/qding-scc-front/index.html返回 index.html返回前端页面请求 http://192.168.251.6/api/qding/user/list转发到 http://127.0.0.1:8162/user/list返回JSON返回接口数据

这张图可以帮助理解:

  • 同一个 IP
  • 同一个 80 端口
  • 浏览器看起来都在访问一台服务器
  • 但 Nginx 会根据 URL 路径,把请求分发到不同地方

四、nginx.confconf.d 到底该怎么分工

这是我一开始很困惑的地方。

很多机器上默认的主配置里会有类似这样的内容:

http {
    include /etc/nginx/conf.d/*.conf;

    server {
        listen 80;
        server_name _;
        root /usr/share/nginx/html;
    }
}

这说明 Nginx 的配置通常分成两层:

1. nginx.conf

更适合放 全局配置,比如:

  • worker 数量
  • 日志格式
  • gzip
  • ssl_protocols
  • include /etc/nginx/conf.d/*.conf
  • 代理公共请求头

2. /etc/nginx/conf.d/*.conf

更适合放 具体业务配置,比如:

  • 某个前端项目的路由
  • 某个后端接口的代理
  • 某个域名的 HTTPS 配置

我的建议

如果你一台服务器上以后要挂:

  • 多个前端
  • 多个后端
  • 多套路径转发

那就 优先用 conf.d 拆配置文件,不要所有东西都堆进 nginx.conf

例如:

/etc/nginx/conf.d/qding-scc-front.conf
/etc/nginx/conf.d/order-front.conf
/etc/nginx/conf.d/user-front.conf

这样更容易维护,也更方便排查问题。


五、location 到底是什么

可以先把它理解成一句话:

location 就是在定义:某一类 URL 请求应该怎么处理。

比如:

location /qding-scc-front/ {
    ...
}

意思就是:

只要请求路径以 /qding-scc-front/ 开头,就按这里面的规则处理。

再比如:

location /api/qding/ {
    ...
}

意思就是:

只要请求路径以 /api/qding/ 开头,就按这里面的规则处理。


六、一个完整的前后端路由例子

先看配置:

server {
    listen 80;
    server_name _;

    location /qding-scc-front/ {
        alias /usr/share/nginx/html/qding-scc-front/;
        index index.html;
        try_files $uri $uri/ /qding-scc-front/index.html;
    }

    location /api/qding/ {
        proxy_pass http://127.0.0.1:8162/;
    }
}

下面逐行解释。


七、location /qding-scc-front/ 是什么意思

这一段表示:

location /qding-scc-front/ {
    ...
}

所有以 /qding-scc-front/ 开头的请求,都会进入这里。

例如:

  • /qding-scc-front/
  • /qding-scc-front/index.html
  • /qding-scc-front/static/js/app.js
  • /qding-scc-front/user/list

八、alias 是什么意思

alias /usr/share/nginx/html/qding-scc-front/;

alias 可以理解成:

把 URL 路径映射到一个真实磁盘目录。

也就是:

浏览器访问 /qding-scc-front/...

Nginx 去 /usr/share/nginx/html/qding-scc-front/... 找文件


实际例子 1:访问静态 JS 文件

浏览器请求:

http://192.168.251.6/qding-scc-front/static/js/app.js

Nginx 会去磁盘上找:

/usr/share/nginx/html/qding-scc-front/static/js/app.js

如果存在,就直接返回这个文件。


九、index 是什么意思

index index.html;

它表示:

如果访问的是一个目录,就默认返回这个目录下的 index.html


实际例子 2:访问首页

浏览器请求:

http://192.168.251.6/qding-scc-front/

这不是一个具体文件,而是一个目录。
此时 Nginx 会默认找:

/usr/share/nginx/html/qding-scc-front/index.html

这通常就是前端页面入口。


十、try_files 是什么意思

try_files $uri $uri/ /qding-scc-front/index.html;

这是前端单页应用里最关键的一句配置之一。

它的意思可以理解成:

  1. 先尝试按请求路径找文件
  2. 找不到就再尝试按目录找
  3. 还找不到,就返回 /qding-scc-front/index.html

为什么前端必须关心这句

因为 Vue、React 这类项目通常有前端路由。

比如你前端页面中定义了路由:

/qding-scc-front/user/list

浏览器打开这个地址时,Nginx 会先尝试找真实文件:

/usr/share/nginx/html/qding-scc-front/user/list

但这个文件通常并不存在。
如果没有 try_files,Nginx 就会直接报 404。

而单页应用的正确逻辑是:

  • 不管你访问 /user/list 还是 /order/detail
  • 最终都先返回同一个 index.html
  • 再由前端 JavaScript 路由接管页面渲染

实际例子 3:访问前端路由页面

浏览器请求:

http://192.168.251.6/qding-scc-front/user/list

Nginx 的处理流程如下:

前端路由磁盘目录Nginx浏览器前端路由磁盘目录Nginx浏览器请求 /qding-scc-front/user/list查找真实文件 /usr/share/nginx/html/qding-scc-front/user/list文件不存在返回 /usr/share/nginx/html/qding-scc-front/index.html返回 index.html返回 index.html前端路由解析 /user/list渲染“用户列表”页面

这就是 try_files 在前端项目里最典型的用途。


十一、proxy_pass 是什么意思

location /api/qding/ {
    proxy_pass http://127.0.0.1:8162/;
}

proxy_pass 的意思是:

把请求转发给另一个服务。

在这里,就是把请求转发给本机 8162 端口上的 Java 后端服务。


实际例子 4:访问后端接口

浏览器请求:

http://192.168.251.6/api/qding/user/list

Nginx 不会去磁盘找文件,
而是会把请求转发到:

http://127.0.0.1:8162/user/list

也就是说:

  • 浏览器以为自己访问的是 Nginx
  • 实际处理接口的是后端 Java 服务

时序图如下:

后端8162Nginx浏览器后端8162Nginx浏览器GET /api/qding/user/list转发到 http://127.0.0.1:8162/user/list返回 JSON 数据返回接口响应

十二、一个服务器部署多个前端、多个后端时怎么配

这也是实际生产里更常见的情况。

假设:

前端项目

  • /qding-scc-front/
  • /order-front/
  • /user-front/

后端服务

  • /api/qding/ -> 8162
  • /api/order/ -> 8163
  • /api/user/ -> 8164

那配置可以写成:

server {
    listen 80;
    server_name _;

    location /qding-scc-front/ {
        alias /usr/share/nginx/html/qding-scc-front/;
        index index.html;
        try_files $uri $uri/ /qding-scc-front/index.html;
    }

    location /order-front/ {
        alias /usr/share/nginx/html/order-front/;
        index index.html;
        try_files $uri $uri/ /order-front/index.html;
    }

    location /user-front/ {
        alias /usr/share/nginx/html/user-front/;
        index index.html;
        try_files $uri $uri/ /user-front/index.html;
    }

    location /api/qding/ {
        proxy_pass http://127.0.0.1:8162/;
    }

    location /api/order/ {
        proxy_pass http://127.0.0.1:8163/;
    }

    location /api/user/ {
        proxy_pass http://127.0.0.1:8164/;
    }
}

这时 Nginx 就像一个统一入口:

  • 访问不同前端路径,返回不同静态站点
  • 访问不同接口路径,转发到不同后端服务

十三、HTTPS、HTTP/2、gzip 又是干什么的

除了路由和转发,Nginx 还经常承担两个重要职责:

  1. HTTPS 安全访问
  2. 前端静态资源传输优化

例如下面这些配置:

listen 443 ssl http2;
server_name iam-uat.cscec1b.net;

ssl_certificate /etc/nginx/ssl/iam-uat.cscec1b.net.pem;
ssl_certificate_key /etc/nginx/ssl/iam-uat.cscec1b.net-key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css text/javascript application/javascript application/json image/svg+xml;
gzip_vary on;

1. listen 443 ssl http2;

表示这个站点开启:

  • 443:HTTPS 默认端口
  • ssl:启用 HTTPS 加密
  • http2:启用更高效的 HTTP/2 协议

实际意义:

  • 浏览器访问的是 https://...
  • 页面资源传输更安全
  • 多个 JS/CSS 文件加载更高效

2. ssl_certificatessl_certificate_key

表示 HTTPS 证书和私钥的位置。
没有这两个,HTTPS 就跑不起来。


3. ssl_protocols TLSv1.2 TLSv1.3;

表示只允许较新的安全协议,禁掉老旧不安全协议。


4. gzip on;

表示开启压缩。

这对前端特别有意义,因为前端项目通常会返回:

  • JS
  • CSS
  • JSON
  • SVG

这些文件压缩后能明显减小体积,页面加载更快。


一个很直观的例子

比如一个前端页面首次加载会请求:

  • main.js 2MB
  • vendor.js 3MB
  • app.css 300KB

如果不开 gzip,这些文件会原样传输。
如果开了 gzip,很多文本资源体积会明显下降,用户打开页面时速度通常会更好。


十四、一个适合业务拆分的推荐配置思路

如果是长期维护的环境,我更推荐:

nginx.conf

只放全局配置,比如:

  • events
  • http
  • 日志格式
  • gzip
  • ssl_protocols
  • include /etc/nginx/conf.d/*.conf

/etc/nginx/conf.d/app-routes.conf

专门放业务站点和接口路由,比如:

server {
    listen 80;
    server_name _;

    location /qding-scc-front/ {
        alias /usr/share/nginx/html/qding-scc-front/;
        index index.html;
        try_files $uri $uri/ /qding-scc-front/index.html;
    }

    location /order-front/ {
        alias /usr/share/nginx/html/order-front/;
        index index.html;
        try_files $uri $uri/ /order-front/index.html;
    }

    location /api/qding/ {
        proxy_pass http://127.0.0.1:8162/;
    }

    location /api/order/ {
        proxy_pass http://127.0.0.1:8163/;
    }
}

这样做的好处是:

  • 全局和业务分离
  • 配置结构更清楚
  • 以后新增前端或后端时更方便

十五、我对 Nginx 前端部署的理解总结

这次把前端部署这块理顺之后,我对 Nginx 的理解比以前清晰了很多。

我现在会把它看成一个统一入口,它主要在做这些事情:

  1. 根据 URL 路径匹配 location
  2. 把前端路径映射到真实静态文件目录
  3. 把单页应用路由回退到 index.html
  4. 把接口请求转发给后端服务
  5. 通过 HTTPS 提供安全访问
  6. 通过 gzip 和 HTTP/2 优化前端资源传输

如果只用一句话总结:

Nginx 不只是“放前端页面的地方”,更是前端静态资源服务、接口转发、安全接入和性能优化的统一入口。


十六、文末速记版

location

匹配某类 URL 请求怎么处理

alias

把 URL 路径映射到真实磁盘目录

index

访问目录时默认返回哪个首页文件

try_files

按顺序尝试找文件,找不到就回退到指定文件

proxy_pass

把请求转发给后端服务

listen 443 ssl http2

开启 HTTPS 和 HTTP/2

gzip

压缩前端静态资源和 JSON 响应,减少传输体积

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值