项目背景
在实际开发中,经常会遇到多个前端系统部署在同一台 Nginx 服务器的场景(如 A 系统部署在根路径/,B 系统部署在子路径/zhgd/)。本文以 Windows 环境下 Nginx 部署 Vue 项目为例,详细记录从静态资源加载失败(Unexpected token ‘<’)、接口 405 Not Allowed 到 404 Not Found 的完整踩坑过程及解决方案,适用于需要多系统共存的开发场景,新手也能快速上手。

一、环境说明

操作系统:Windows 10/11
Nginx 版本:nginx-1.24.0
前端框架:Vue 2/Vue 3(单页应用 SPA)
部署场景:A 系统(根路径/)+ B 系统(子路径/zhgd/)共存,共享同一 Nginx 端口(8088)
后端地址:B 系统后端接口地址http://172.27.0.145:8081

二、核心需求

B 系统前端部署在 Nginx 的html/zhgd目录,通过http://172.27.0.145:8088/zhgd/访问;
B 系统静态资源(JS/CSS/ 图片)正常加载,无Unexpected token '<'错误;
B 系统接口(如/zhgd/prod-api/logout、/zhgd/prod-api/getInfo)能正确代理到后端,无 405/404 错误;
与 A 系统(根路径/)互不干扰,独立访问

三、完整踩坑过程及解决方案

坑 1:静态资源加载失败(Unexpected token ‘<’)
现象
访问http://172.27.0.145:8088/zhgd/,控制台报Uncaught SyntaxError: Unexpected token ‘<’,Network 面板显示 JS/CSS 资源返回 404,响应类型为text/html。
原因
Vue 项目打包时publicPath配置错误,静态资源请求路径缺少/zhgd/前缀(如请求/static/js/app.js而非/zhgd/static/js/app.js);
Nginx 配置中alias路径使用相对路径或缺少结尾斜杠,导致路径映射错误;
Windows 环境下 Nginx 配置未使用绝对路径,路径解析歧义。
解决方案

Vue 项目打包配置修正
修改.env文件(或.env.production),指定应用访问路径和接口基础路径:

# .env文件配置
VUE_APP_TITLE = 智慧工地管理平台
VUE_APP_CONTEXT_PATH = '/zhgd/'  # 对应publicPath,必须带结尾斜杠
VUE_APP_BASE_API = '/zhgd/prod-api'  # 接口基础路径,带/zhgd前缀

Nginx 静态资源配置修正(Windows 绝对路径)
放弃alias,使用root+ 绝对路径,避免路径歧义,配置如下:

 # A系统核心端口:8088(保留所有原始配置,新增B系统配置)
    server {
        listen       8088;
        server_name  localhost;

        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        # ========== A系统:原始配置,完全保留 ==========
         location / {
             root   html;
             index  index.html index.htm;
             try_files $uri $uri/ /index.html =404;
         }
		
		location /api/{
			proxy_set_header Host $http_host;
			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;
			proxy_pass http://172.27.0.145:6115/;
			#rewrite "^/api/(.*)$" /$1 break;
		}

       # ========== B系统:新增配置 /zhgd/ 路径 ==========
	   # B系统配置(修改后,和A系统逻辑对齐)
		location ^~ /zhgd/ {
			# 核心1:用root替代alias,且写绝对路径(替换为你的Nginx实际安装路径)
			root   "D:/nginx-1.24.0/html";  
			index  index.html index.htm;
			# 核心2:兜底路径改为/zhgd/index.html(适配单页应用路由)
			try_files $uri $uri/ /zhgd/index.html;
			
			# 核心3:静态资源子配置和A系统保持一致(绝对路径+完整后缀)
			location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
				root   "D:/nginx-1.24.0/html";  # 绝对路径,和外层一致
				expires 1d;
				add_header Cache-Control "public";
				try_files $uri =404;
			}
		}
		
		# 2. B系统接口代理(仅修改这一行:匹配/zhgd/prod-api/)
		location ^~ /prod-api/ {  # 原配置是/prod-api/,新增/zhgd/前缀
			
			# 跨域配置(保留)
			add_header Access-Control-Allow-Origin *;
			add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
			add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
			
			# OPTIONS预检请求(保留)
			if ($request_method = 'OPTIONS') {
				return 204;
			}
		
			# 透传客户端信息(保留)
			proxy_set_header Host $http_host;
			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;
			
			# rewrite规则(保留,已正确去掉/zhgd前缀)
			rewrite ^/zhgd/prod-api/(.*)$ /prod-api/$1 break;
			proxy_pass http://172.27.0.145:8081/;
			
			# 超时配置(保留)
			proxy_connect_timeout 30s;
			proxy_send_timeout 30s;
			proxy_read_timeout 30s;
		
			# 新增:确保POST请求体正常转发(解决405关键补充)
			proxy_http_version 1.1;
			proxy_set_header Connection "";
		}

坑 2:接口 POST 请求 405 Not Allowed(/zhgd/prod-api/logout)

现象
前端发起POST http://172.27.0.145:8088/zhgd/prod-api/logout请求,返回 405 Not Allowed,后端已确认/logout接口支持 POST 方法(@PostMapping(“/logout”))。
原因
Nginx 接口代理路径匹配错误:代理配置location ^~ /prod-api/未包含/zhgd/前缀,无法匹配前端请求;
缺少跨域配置,OPTIONS 预检请求被拦截;
未配置 POST 请求体透传,导致后端无法识别请求方法。
解决方案
修正 Nginx 接口代理配置,匹配/zhgd/prod-api/路径,补充跨域和 POST 透传配置:

# B系统接口代理配置(/zhgd/prod-api/前缀)
location ^~ /zhgd/prod-api/ {
    # 跨域配置:放行POST/OPTIONS等方法和请求头
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
    add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
    
    # 处理OPTIONS预检请求(POST请求必须配置)
    if ($request_method = 'OPTIONS') {
        return 204;
    }

    # 透传客户端信息到后端
    proxy_set_header Host $http_host;
    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;
    
    # 重写路径:去掉/zhgd前缀,转发为/prod-api/xxx(匹配后端接口路径)
    rewrite ^/zhgd/prod-api/(.*)$ /prod-api/$1 break;
    proxy_pass http://172.27.0.145:8081/;
    
    # 确保POST请求体正常转发(关键配置)
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    
    # 接口超时配置
    proxy_connect_timeout 30s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
}

坑 3:接口 GET 请求 404 Not Found(/zhgd/prod-api/getInfo)
现象
前端发起GET http://172.27.0.145:8088/zhgd/prod-api/getInfo请求,返回 404 Not Found。
原因
Nginx 转发路径与后端实际接口路径不匹配(如后端接口无/prod-api前缀,实际路径为/getInfo);
后端server.servlet.context-path配置与 Nginx 转发规则不一致。
解决方案
验证后端实际接口路径
直接访问后端地址,确认接口真实路径:
测试 1(带/prod-api前缀):GET http://172.27.0.145:8081/prod-api/getInfo
测试 2(无前缀):GET http://172.27.0.145:8081/getInfo
测试 3(/dev-api前缀):GET http://172.27.0.145:8081/dev-api/getInfo
假设测试 2 返回 200,说明后端接口实际路径为/getInfo(无/prod-api前缀)。

修正 Nginx 重写规则
调整rewrite规则,去掉多余的/prod-api前缀:

location ^~ /zhgd/prod-api/ {
    # 保留跨域/透传/超时配置...
    
    # 核心修正:转发为/$1(而非/prod-api/$1)
    rewrite ^/zhgd/prod-api/(.*)$ /$1 break;
    proxy_pass http://172.27.0.145:8081/;
}

四、最终可用的完整 Nginx 配置

 # A系统核心端口:8088(保留所有原始配置,新增B系统配置)
    server {
        listen       8088;
        server_name  localhost;

        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        # ========== A系统:原始配置,完全保留 ==========
         location / {
             root   html;
             index  index.html index.htm;
             try_files $uri $uri/ /index.html =404;
         }
		
		location /api/{
			proxy_set_header Host $http_host;
			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;
			proxy_pass http://172.27.0.145:6115/;
			#rewrite "^/api/(.*)$" /$1 break;
		}

       # ========== B系统:新增配置 /zhgd/ 路径 ==========
	   # B系统配置(修改后,和A系统逻辑对齐)
		location ^~ /zhgd/ {
			# 核心1:用root替代alias,且写绝对路径(替换为你的Nginx实际安装路径)
			root   "D:/nginx-1.24.0/html";  
			index  index.html index.htm;
			# 核心2:兜底路径改为/zhgd/index.html(适配单页应用路由)
			try_files $uri $uri/ /zhgd/index.html;
			
			# 核心3:静态资源子配置和A系统保持一致(绝对路径+完整后缀)
			location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
				root   "D:/nginx-1.24.0/html";  # 绝对路径,和外层一致
				expires 1d;
				add_header Cache-Control "public";
				try_files $uri =404;
			}
		}
		
		# 2. B系统接口代理(仅修改这一行:匹配/zhgd/prod-api/)
		location ^~ /prod-api/ {  # 原配置是/prod-api/,新增/zhgd/前缀
			
			# 跨域配置(保留)
			add_header Access-Control-Allow-Origin *;
			add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
			add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
			
			# OPTIONS预检请求(保留)
			if ($request_method = 'OPTIONS') {
				return 204;
			}
		
			# 透传客户端信息(保留)
			proxy_set_header Host $http_host;
			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;
			
			# rewrite规则(保留,已正确去掉/zhgd前缀)
			rewrite ^/zhgd/prod-api/(.*)$ /prod-api/$1 break;
			proxy_pass http://172.27.0.145:8081/;
			
			# 超时配置(保留)
			proxy_connect_timeout 30s;
			proxy_send_timeout 30s;
			proxy_read_timeout 30s;
		
			# 新增:确保POST请求体正常转发(解决405关键补充)
			proxy_http_version 1.1;
			proxy_set_header Connection "";
		}

五、关键配置总结与避坑要点

  1. Vue 项目打包核心配置
    publicPath必须与 Nginx 子路径一致(如/zhgd/),结尾带斜杠;
    接口基础路径VUE_APP_BASE_API需包含 Nginx 子路径前缀(如/zhgd/prod-api)。
  2. Nginx 配置避坑要点
    Windows 环境必须使用绝对路径(如D:/nginx-1.24.0/html),避免相对路径歧义;
    静态资源配置使用root而非alias,简化路径映射逻辑;
    接口代理路径必须与前端请求路径一致(如/zhgd/prod-api/),否则无法匹配;
    跨域配置必须放行 OPTIONS 预检请求,POST 请求需配置proxy_http_version 1.1和proxy_set_header Connection “”;
    重写规则rewrite需与后端接口路径匹配,通过直接访问后端接口验证真实路径。
  3. 问题排查技巧
    静态资源错误:查看 Network 面板,确认请求路径是否包含子路径前缀(如/zhgd/static/js/),响应类型是否为对应资源类型(而非text/html);
    接口 405 错误:检查 Nginx 代理路径是否匹配、跨域配置是否完整、POST 请求体透传配置是否添加;
    接口 404 错误:直接访问后端接口验证真实路径,调整 Nginxrewrite规则。

六、结语

本文详细记录了 Windows 环境下 Nginx 部署多系统 Vue 项目的常见问题及解决方案,核心在于确保前端打包路径与 Nginx 配置一致、Nginx 转发路径与后端接口一致。通过本文的配置和避坑要点,可快速解决静态资源加载失败、接口 405/404 等问题,实现多系统在同一 Nginx 服务器的稳定共存。如果遇到其他问题,欢迎在评论区交流!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐