nginx 部署 vue 项目,给访问路径加前缀,配置同源策略
一、Nginx 的安装
官网下载并解压 nginx 压缩包。官网地址:nginx news
二、Nginx 常见命令
1.1、nginx 命令:
指定配置文件:nginx -c filename
验证配置(nginx.conf)是否正确: nginx -t
查看 Nginx 的版本号:nginx -V
启动 Nginx:start nginx
快速停止或关闭 Nginx:nginx -s stop
正常停止或关闭 Nginx:nginx -s quit
彻底杀死多个线程:taskkill /f /t /im nginx.exe
配置文件修改重装载命令 / 重启:nginx -s reload
1.2、其它常用命令:
端口号查看:netstat -ano|findstr :8090
端口号服务:tasklist|findstr "12824"
打开文件: notepad hosts
hosts 修改后释放 命令行:ipconfig/release
重建本地 DNS 缓存 命令行:ipconfig /flushdns
三、Vue 中添加访问路径。比如 http://www.lpnm.com/CKManage
3.1、vue 的 vue.config.js 中进行配置
3.2、接着在对应的 router/index.js 中 添加路由配置
3.3、yarn build 项目后,把打包后的文件,放在 nginx 路径下 html 文件夹下,新建一个文件夹 NeiMeng, 然后把包对应放进去
3.4、nginx 路径加前缀和不添加前缀配置
-
server {
-
listen 8071;
-
server_name www.lpnm.com;
-
# 设置跨域访问权限
-
add_header Access-Control-Allow-Origin *;
-
location / {
-
root html\NeiMeng\BaseManage;
-
index index.html index.htm;
-
try_files $uri $uri/ @router; # 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
-
}
-
location @router {
-
rewrite ^.*$ /index.html last;
-
}
-
}
-
-
server {
-
listen 8072;
-
server_name www.lpnm.com;
-
# 设置跨域访问权限
-
add_header Access-Control-Allow-Origin *;
-
location /CKManage {
-
alias html\NeiMeng\CKManage;
-
index index.html index.htm;
-
try_files $uri $uri/ @router; # 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
-
}
-
location @router {
-
rewrite ^.*$ /CKManage/index.html last;
-
}
-
}
3.5、配置同源策略
两个不同端口的地址 www.lpnm.com:8071;www.lpnm.com:8072; 想通过 www.lpnm.com:8070 同时访问这两个地址
配置如下:
-
#配置代理:
-
server {
-
listen 8070;
-
server_name www.lpnm.com;
-
location / {
-
proxy_pass http://www.lpnm.com:8071/;
-
}
-
location /CKManage {
-
proxy_pass http://www.lpnm.com:8072/CKManage;
-
}
-
一、前言
前后端分离后,如果想将前后端项目都放在同一台电脑上启动与开发,可以使用 nginx。
现将配置方法总结如下。
二、后端配置方法
1. 如果是 springboot 项目,要注意 application.yml 中的:
-
server:
-
port: 8080
-
context-path: /survey
类似这样的配置,说明后端项目启动后,端口是 8080,前缀路径为 /survey。
2. 注意 pom.xml 中,如果有以下配置:
-
<plugin>
-
<groupId>org.apache.tomcat.maven</groupId>
-
<artifactId>tomcat7-maven-plugin</artifactId>
-
<configuration>
-
<path>/survey</path>
-
<port>8080</port>
-
</configuration>
-
</plugin>
这说明项目打好包启动后,端口是 8080,前缀路径为 /survey。
3. 查看 XXXController.java,注意以下部分:
(1) 类上的 RequestMapping 注解
-
@Controller
-
@RequestMapping("/survey-api")
-
public class LoginController{}
这个说明,此 controller 中具体的路径前有一个前缀,为 /survey-api。
(2) 方法上的 RequestMapping/GetMapping/PostMapping 等注解
-
"/login")(
-
public void login(HttpServletRequest req, HttpServletResponse resp){}
这个说明访问这个后台方法的路径的最后部分为 /login。
4. 因此,按照上方的例子,访问后台方法 login 的具体的 url 为:
http://localhost:8080/survey/survey-api/login
localhost 是本地 ip 的意思,如果后台项目启动在其它主机上,则访问时换成为其它主机的 ip。
三、前端配置方法
1. 前端可能会有一个总的配置文件,记录一个 ip,具体代码中只使用这个 ip 的引用。
就是声明一个全局变量,例如 IPCONFIG = 10.123.123.123:8081,之后用 IPCONFIG 拼接后缀形成 url。
这个全局变量可能用来拼接前端页面的 url,也有可能用来拼接后台接口的 url。
因此,打前端包时,应该修改这个参数为存放前端项目或后端项目的电脑的 IP + 端口。
2. 以本人接触的项目为例,vue 项目打好包后,生成 dist 文件夹,其中有一个 static 文件夹与 index.html 文件;
static 文件夹中,有一个 ipConfig.js;
ipConfig.js 中,配置了全局变量:
-
const IPCONFIG="http://10.123.123.123:8081" //本地路径,开发用
-
//const IPCONFIG="http://www.prodMyCompany.com" //生产路径,生产用
IPCONFIG 会被拼接为一些 url,进行参数传递与验签用。
10.123.123.123:8081 是本地电脑的 ip:nginx 监听的端口;
前端项目与后台项目都准备放在 10.123.123.123 上。(后台项目端口为 8080,下方 nginx 会配置)
四、nginx 配置方法
1. 为了使得配置文件不太混乱,使用新建配置文件并引入的方法。
2. 打开 D:/nginx-1.18.0/conf/nginx.conf 文件 (文件路径为参考样例),在末尾增加以下语句:
-
include D://nginx-1.18.0//conf//upstream.conf;
-
include D://nginx-1.18.0//conf.d//*.conf;
这两句的意思是,让 nginx.conf 配置文件包含 /conf/upstream.conf 文件,以及 conf.d 文件夹下的所有.conf 文件。
3. 在 conf 文件夹中创建 upstream.conf 文件,用来写 upstream 信息,例如:
-
upstream project_survey {
-
server localhost:8080;
-
#server 10.123.123.123:8080;
-
}
配置后,可以供后续使用;
准备把后端项目放到本地计算机上,用 8080 端口访问,用 project_survey 表示;
因此这么写。
4. 在 D:/nginx-1.18.0 / 文件夹中创建 conf.d 文件夹,在其中创建一个 my.conf 文件,用来写具体的 nginx 映射,例如:
-
server {
-
listen 8081;
-
#listen 10.123.123.123:8081;
-
server_name 10.123.123.123;
-
#server_name www.hao1.com;
-
#server_name www.hao2.com;
-
#server_name localhost;
-
-
-
location / {
-
root D:\\project\\web;
-
try_files $uri $uri/ /index.html;
-
index index.html;
-
}
-
-
location /survey-wrong/web {
-
rewrite ^.+ http://localhost:8081/;
-
#rewrite ^.+ http://localhost:8081/ break;
-
}
-
-
location /project_survey {
-
expires -1;
-
proxy_set_header Host $http_host;
-
proxy_read_timeout 1800;
-
proxy_connect_timeout 1800;
-
proxy_send_timeout 1800;
-
proxy redirect off;
-
proxy_set_header X-Real-IP $remote_addr;
-
proxy_set_header REMOTE-HOST $remote_addr;
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-
client_max_body_size 2g;
-
-
proxy_pass http://project_survey;
-
}
-
-
location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ {
-
root D:\\project\\web;
-
proxy_temp_path D:\\project\\web;
-
}
-
-
}
(1) listen 8081,说明 nginx 监听的是 8081 的请求。(如果配置了 ip,那么 server_name 就不生效了)
(2) server_name,配置域名。
当收到一个 url 请求,nginx 会先匹配 listen 中的 ip;如果没有配置 ip,再匹配 server_name;然后匹配 listen 中的端口。
上方例子配置的 server_name 是 10.123.123.123,listen 是 8081,因此收到 http://10.123.123.123:8081 的请求时,会走这个匹配规则,因为 server_name 与端口匹配成功了;
如果收到 http://localhost:8081 的请求时,也会走这个匹配规则,因为端口匹配成功了。
/*
如果本地 ip 不是 10.123.123.123,那么不会收到形如 http://10.123.123.123:8081 的请求,只会收到 http://localhost:8081 的请求,或者 http:// 本地 IP:8081 的请求,或者 http:// 本地域名:8081 的请求。
因此 server_name 可以配不配置都可以,只要 listen 配置了就可以了。
*/
参考:https://blog.csdn.net/qq_40737025/article/details/85053164
(3) location / 中配置的 D:\\project\\web,是前端项目所在的文件夹,其中 web 文件夹中有 index.html 文件以及 static 文件夹。这样使得请求 url 形如 / 的可以访问到本地的前端项目。
如访问 http://localhost:8081/,可以访问到 D:\\project\\web\\index.html。
root,将 url 中的头部分替换为指定部分,例如将 http://localhost:8081 替换为 D:\\project\\web。
try_files,先寻找 $uri,如果资源不存在,寻找 $uri/,如果资源还不存在,寻找 /index.html。
index,指定页面初始页,如果访问的 url 没有指定页面,则访问 index.html。
参考:https://www.cnblogs.com/boundless-sky/p/9459775.html
(4) location /survey-wrong/web,表示请求 url 中包含 /survey-wrong/web 时,全部重定向为 http://localhost:8081/,也就是重定向到首页。
其中,^.+ 是正则表达式,表示要匹配从第一个 (^) 开始、任意字符 (.)、有 1 - 多个 (+) 的内容;
匹配后,直接全部替换为指定地址。
因为 rewrite 进行了重定向,因此会从头开始重新匹配该 nginx 文件中配置的规则。(接着会走 location /,从而访问到 index.html)
/*
rewrite 后还可以加参数,例如 break 表示后续不再匹配其余规则等。
参考:https://www.cnblogs.com/brianzhu/p/8624703.html
*/
(5) location /project_survey,表示当请求 url 包含 /project_survey 时,会被替换为 proxy_pass 中的内容,http://project_survey;
而 project_survery 会被替换为 upstream 中的 localhost:8080,这个是后端项目的地址了。
例如访问
【http://localhost:8081/project_survery/survey/survey-api/login】
实际上访问的是
【http://localhost:8080/survey/survey-api/login】
nginx 会将匹配规则以及之前的部分全部替换为 proxy_pass 中的内容,后半部分保留;
对【location /project_survey】来说,
会将【http://localhost:8081/project_survery】替换为【http://localhost:8080】,然后拼接上剩余的【/survey/survey-api/login】
就得到了【http://localhost:8080/survey/survey-api/login】
这样就访问到后台接口了。
(6)location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ ,
[.*] 表示任意字符、0 - 多个,
[\.] 表示字符.,
[$] 是字符串结尾位置,
也就是 url 请求中任意以.gif 或.jpg 或.jpeg 或.png 或.css 或.js 或.ico 结尾的,走这个匹配规则。
root 表示根路径要被替换为指定路径,
例如访问 http://localhost:8081/static/ipConfig.js
会将 http://localhost:8081 替换为
D:\\project\\web
实际访问了 D:\\project\\web/static/ipConfig.js
proxy_temp_path 为存储承载从代理服务器接收到的数据的临时文件定义目录。
参考:http://www.weixueyuan.net/a/662.html
5. 启动 nginx,启动后台项目,访问前端网页或后台接口,测试前后台能否成功通信。
例如访问前端 index.html,为【http://localhost:8081/】。
五、总结
1. 确定后端接口 url。(包含 ip、端口、controller 路径)
例如后端接口为:
http://127.1.2.3:8080/controller/login
2. 修改前端全局变量,改为本地的 ip+nginx 监听的端口。
例如:
const IPCONFIG = "http://127.1.2.3:8081"
3. 修改 nginx 配置文件,使得通过 url 可以访问到前端页面,并且前端页面可以发送请求给后台接口。
例如:
-
server {
-
listen 8081;
-
server_name localhost;
-
-
location / {
-
root D:\\project\\web;
-
try_files $uri $uri/ /index.html;
-
index index.html;
-
}
-
-
location /controller {
-
proxy_pass http://localhost:8080/controller;
-
}
-
-
location ~ .*\.(gif|jpg|jpeg|png|css|js|ico)$ {
-
root D:\\project\\web;
-
proxy_temp_path D:\\project\\web;
-
}
-
}
(1) 访问 http://localhost:8081 / 或者 http://127.1.2.3:8081/,可以跳转到前端页面 D:\\project\\web\\index.html
(2) 前端页面发送请求给后台,规定 url 中要包含 /controller,这样就会被 nginx 转换为真实的后台 url,例如发送 [http://127.1.2.3:8081/controller/login],会把 [http://127.1.2.3:8081/controller] 替换为 [http://localhost:8080/controller],然后拼接剩余的 [/login],就访问到了 [http://127.1.2.3:8080/controller/login].
(3) 因为本地 ip 是 127.1.2.3,所以 localhost 等价于 127.1.2.3.
六、后记
1. 本文中的配置信息根据真实项目改编优化;如果有误,欢迎指出,作者会继续修改完善。
2. 关于 nginx 配置中,location 中末尾的【/】与 proxy_pass 中末尾的【/】的说明:
(1) 如果这么写:
-
location /project_survey {
-
proxy_pass http://127.1.2.3:8080;
-
}
当访问 http://localhost:8080/project_survey/abc/abc 时,
由于存在【/project_survey】,匹配成功,nginx 会将【/project_survey】及之前的部分全部替换为 proxy_pass 中的内容,并保留之后的部分,
相当于访问了 http://127.1.2.3:8080/abc/abc。
(2) 如果这么写:
-
location /project_survey/ {
-
proxy_pass http://127.1.2.3:8080/;
-
}
当访问 http://localhost:8080/project_survey/abc/abc 时,
由于存在【/project_survey/】,匹配成功,nginx 会将【/project_survey/】及之前的部分全部替换为 proxy_pass 中的内容,并保留之后的部分,
相当于访问了 http://127.1.2.3:8080/abc/abc。
(3) 如果这么写:
-
location /project_survey {
-
proxy_pass http://127.1.2.3:8080/;
-
}
当访问 http://localhost:8080/project_survey/abc/abc 时,
由于存在【/project_survey】,匹配成功,nginx 会将【/project_survey】及之前的部分全部替换为 proxy_pass 中的内容,并保留之后的部分,
相当于访问了 http://127.1.2.3:8080//abc/abc,会多了一个【/】,倒是影响不太大。
(4) 如果这么写,就有问题了:
-
location /project_survey/ {
-
proxy_pass http://127.1.2.3:8080;
-
}
当访问 http://localhost:8080/project_survey/abc/abc 时,
由于存在【/project_survey/】,匹配成功,nginx 会将【/project_survey/】及之前的部分全部替换为 proxy_pass 中的内容,并保留之后的部分,
相当于访问了 http://127.1.2.3:8080abc/abc,少了一个【/】,此时路径就会出错。
(5) 所以概括为:要加都加,要不加都不加。
3.nginx 中 location 包含正则表达式的说明
(1) 包含正则表达式时,有时候会不按照最长匹配原则,而是按照匹配的先后顺序。如下:
-
upstream survey{
-
server 127.1.2.3:8080;
-
}
-
-
location ~ /survey(.*) {
-
set $name survey;
-
proxy_pass http://$name/survey1$1$is_args$args;
-
}
-
-
location ~ /survey/dev/search(.*) {
-
set $name survey;
-
proxy_pass http://$name/survey2/dev/search$1$is_args$args;
-
}
当访问 http://localhost:8080/survey/dev/search/abc 时,
本来希望被转发到:
http://127.1.2.3:8080/survey2/dev/search/abc
实际被转发到:
http://127.1.2.3:8080/survey1/dev/search/abc
原请求同时符合这两个正则表达式,但是 nginx 走了上方的第一个匹配,而不是走最长匹配原则。
如果想实现需求,需要将上方的匹配规则换一下位置,才会走 survey2 那个:
-
upstream survey{
-
server 127.1.2.3:8080;
-
}
-
-
location ~ /survey/dev/search(.*) {
-
set $name survey;
-
proxy_pass http://$name/survey2/dev/search$1$is_args$args;
-
}
-
-
location ~ /survey(.*) {
-
set $name survey;
-
proxy_pass http://$name/survey1$1$is_args$args;
-
}
(2) 上方代码参数解释:
~:区分大小写匹配
(.*):匹配 0 - 多个任意字符
$name:声明一个变量,值为 upstream 中的 survey,下方的 proxy_pass 使用时会被转为 ip。
$1:指 location 中的正则表达式匹配成功后的字符,即 (.*) 匹配得到的字符。
$is_args:请求中是否包含参数 (key-value),如果有,则继续拼接后面的字符;没有则为空。
$args:请求中的参数,没有则为空。
4.nginx 配置文件修改后没有生效的一种可能性
windows 下,启动 nginx.exe 或者用 cmd 启动 nginx 后,nginx 就会在后台运行;
之后关闭启动着 nginx 的 cmd 窗口、或者输入命令 nginx -s stop,有可能并不会完全关闭 nginx;
导致修改配置文件后、再次启动 nginx 时,配置文件没有生效 —— 是因为请求走到了使用旧配置文件的仍然存活的 nginx 上。(此时打开任务管理器可以发现多个 nginx 进程,之前的 + 新启动的)
解决方法是 cmd 输入:【taskkill /IM nginx.exe /F】,可以关闭所有启动了的 nginx;之后启动一个新的 nginx 即可。