Vite + Vue SPA 在子路径部署(内外网访问+Nginx 反向代理)

Vite + Vue SPA 在子路径部署(内外网访问+Nginx 反向代理)

问题背景

概述

最近部署了一个基于 Vite + Vue.js + Vuetify 的 SPA 项目。

项目并不是部署在根路径,而是部署在子路径:

复制代码
/product-calculate/

同时存在两个访问场景:

我需要内网和外网均能访问系统页面

以下是详细信息

内网访问

复制代码
http://<内网ip>:<项目端口>/product-calculate/

外网访问

复制代码
https://<公网域名>/product-calculate/

此外,由于我的域名只是用来我个人访问的,所以我希望如果直接访问域名,显示我用于占位的"comming soon"。只有访问特定的路径才会显示我的系统页面。

网络结构

复制代码
浏览器
   │
   │
公网 Nginx(反向代理)
   │
   │
内网 Nginx(静态资源 + API代理)
   │
   │
Vue 打包产物 dist

并且 API 服务在内网api网关注册了,名称为:

复制代码
/product-calculate-service/

一、需求总结

最终需要实现:

1️⃣ SPA 子路径部署

复制代码
/product-calculate/

2️⃣ 支持 SPA 刷新

例如:

复制代码
/product-calculate/products

刷新不能 404。

3️⃣ 同时支持内网 + 外网访问

内网:

复制代码
http://<内网ip>:<项目端口>/product-calculate/

外网:

复制代码
https://<公网域名>/product-calculate/

4️⃣ API 统一路径

复制代码
/product-calculate-service/*

5️⃣ 公网通过反向代理访问内网服务


二、遇到的问题

在部署过程中,遇到了几个典型 SPA 部署问题。


1 刷新页面 404

例如访问:

复制代码
/product-calculate/products

刷新后:

复制代码
404 Not Found

原因:

SPA 使用 history 模式 ,服务器并没有 /products 这个真实文件。

解决方案:

Nginx 需要使用:

复制代码
try_files $uri $uri/ /index.html;

让所有不存在的路径回退到 index.html


2 静态资源 404

浏览器报错:

复制代码
GET /product-calculate/assets/js/index.js 404

原因:

Nginx root 路径与子路径不匹配。

解决办法:

使用 rewrite 去掉 /product-calculate 前缀:

复制代码
rewrite ^/product-calculate/(.*)$ /$1 break;

这样:

复制代码
/product-calculate/assets/js/app.js

会映射为:

复制代码
/assets/js/app.js

从而正确找到 dist 中的文件。


3 MIME type 错误

浏览器报错:

复制代码
Failed to load module script: Expected a JavaScript module but server responded with text/html

原因:

JS 文件被 try_files fallback 到 index.html

本质原因依然是 路径解析错误

解决办法:

保证 rewrite 后能正确匹配真实文件路径。


4 公网刷新变成 "comming soon"

刷新:

复制代码
https://<公网域名>/product-calculate/products

返回:

复制代码
comming soon

原因:

公网 Nginx 的:

复制代码
error_page 404 =200 /index.html;

会在 公网服务器本地查找 index.html

但 index.html 在 内网服务器

导致 fallback 到:

复制代码
location /

返回默认页面。

解决办法:

SPA fallback 只在内网处理。

公网只做 反向代理


5 公网 rewrite 导致 404

公网配置:

复制代码
rewrite ^/product-calculate/(.*)$ /$1 break;

导致:

复制代码
/product-calculate/products

被转发为:

复制代码
/products

而内网服务实际路径是:

复制代码
/product-calculate/products

最终 404。

解决办法:

公网 不要 rewrite,直接代理。


三、最终解决方案

采用 双层 Nginx 架构

复制代码
公网 Nginx
   │
   │ proxy_pass
   │
内网 Nginx
   │
   │ try_files (SPA fallback)
   │
Vue dist

四、最终内网 Nginx 配置

复制代码
server {
    listen <项目端口>;
    server_name <内网ip>;

    root /www/wwwroot/vue/product-calculate/dist;
    index index.html;

    location /product-calculate/ {

        # 去掉前缀
        rewrite ^/product-calculate/(.*)$ /$1 break;

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

    location /product-calculate-service/ {
        proxy_pass http://<内网ip>:<后端网关端口>/product-calculate-service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

核心逻辑:

复制代码
rewrite → 去掉子路径前缀
try_files → SPA fallback

五、最终公网 Nginx 配置

公网只做 反向代理

复制代码
location ^~ /product-calculate/ {

    proxy_pass http://<内网ip>:<项目端口>;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

API 代理:

复制代码
location /product-calculate-service/ {
    proxy_pass http://<内网ip>:<后端网关端口>/product-calculate-service/;
}

六、最终访问效果

内网访问:

复制代码
http://<内网ip>:<项目端口>/product-calculate/
http://<内网ip>:<项目端口>/product-calculate/products

外网访问:

复制代码
https://<公网域名>/product-calculate/
https://<公网域名>/product-calculate/products

API:

复制代码
/product-calculate-service/*

全部正常。


七、经验总结

部署 SPA 时有三个关键原则:

1 SPA fallback 只在一个地方处理

推荐:

复制代码
内网 Nginx → try_files
公网 Nginx → proxy

否则容易出现:

  • 404
  • MIME type 错误
  • fallback 错乱

2 子路径部署必须处理路径

两种方式:

方案一:

复制代码
rewrite 去掉前缀

方案二:

复制代码
alias

3 反向代理不要随便 rewrite

如果后端本身已经处理路径:

复制代码
proxy_pass 直接转发

不要额外 rewrite。


八、最终架构

复制代码
Browser
   │
   │
<公网域名>
   │
   │  (公网 Nginx)
   │
proxy_pass
   │
   │
<内网ip>:<项目端口>
   │
   │  (内网 Nginx)
   │
try_files
   │
   │
Vue dist

九、适用场景

这套方案适用于:

  • Vue / Vite SPA
  • React SPA
  • 子路径部署
  • 内外网混合访问
  • API 反向代理
  • 单页应用刷新

如果以后部署新的 SPA 项目,只需要修改/product-calculate为你的新路径即可复用整套方案。

相关推荐
云计算磊哥@10 分钟前
运维开发宝典059-大型网站nginx服务器管理全集5
服务器·nginx·运维开发
meilindehuzi_a1 小时前
Vue3组件样式隔离与组件通信实战:从 scoped、props 校验到记事本应用
前端·javascript·vue.js
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-07-28
前端·神经网络·react.js·搜索引擎·前端框架
陈随易8 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
Highcharts.js8 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC9 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
鱼樱前端9 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
_lucas9 小时前
给知识库网站接入AI问答
前端·ai编程·全栈
前端糕手10 小时前
前端面试题大全:JavaScript + Vue3 + React + TypeScript + 工程化 + 性能优化
前端
我不叫武11 小时前
一个用 Rust 写的离线编码查询桌面工具
前端