前言:第一次部署项目,就差前端,结果一直返回 Nginx 欢迎页,问了好几个 AI 都没给我查到问题所在,结果是因为宝塔配置 Nginx 服务时自动给覆盖了默认配置,导致完全破坏我的项目运行目录。真的得不吐不快  (╯‵□′)╯ !


一、介绍项目环境

前后端分离项目:

  • 前端:Vue 3 + Vite 8 + Vue Router(History 模式)
  • 后端:Java SpringBoot 项目
  • 部署环境:Windows Server + 宝塔面板
  • 目标:通过 Nginx 部署前端静态文件,并反向代理后端 API

二、构建阶段踩坑

踩坑 1:环境变量配置很重要

.env(通用)

所有环境(开发、生产、测试)都会加载它。通常用来存放完全公开、所有环境都相同的变量,比如 VITE_APP_NAME=我的项目

.env.development(开发)

开发阶段下的环境变量,仅在 dev 或 serve 模式下加载。会覆盖 .env 中同名的变量。一般存放假数据或本地服务地址

.env.prodution(生产)   

生产阶段下的环境变量,仅在 build 或 start 模式下加载。会覆盖 .env 中同名的变量。用以存放真实域名和正式配置

  • 前端变量必须带前缀:在 Vite 中,只有以 VITE_ 开头的变量才会被暴露给前端代码(如 import.meta.env.VITE_XXX)。如果不带此前缀使用,它只在 Node.js 服务端(如 vite.config.js)中有效,前端页面读不到。

  • 编译时“硬替换”:前端环境变量不是运行时的系统变量,而是在 npm run build 打包时就被静态替换进代码里的。这意味着:不能在构建完成后,通过修改服务器的 .env.production 文件来改变前端页面的行为——必须重新打包。

注意:如果有 .env.local 或 .env.development.local,它们的优先级最高(通常被 .gitignore 忽略,用于本地机器特有的覆盖,比如本地调试接口)。


踩坑 2:生产包中包含 Vue DevTools

在 vite.config.js 中直接注册了 vueDevTools() 插件,导致生产构建也会打包进去。用户可通过 Alt+Shift+D 快捷键打开调试面板,暴露组件树和 API 请求信息。

plugins: [
  vue(),        # 按环境条件引入
  ...(mode === 'development' ? [vueDevTools()] : []),
]

建议直接在生产构建前移除该插件。

三、Nginx 配置阶段踩坑

踩坑 3:SPA History 路由未配置回退

Vue Router 使用 createWebHistory() 时,路由路径是真实的 URL(如 /user/favourites)。用户直接刷新或访问这些路径时,Nginx 会去磁盘寻找物理文件,找不到则返回 404。

添加 nginx 配置解决

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

踩坑 4:宝塔自动生成的多余配置

宝塔新建站点时,会自动生成并 include 了大量与本项目无关的配置:

自动配置的部分 nginx :

#proxy-cache
location ~ /purge(/.*) {   # 缓存清除配置,用于手动清除 Nginx 代理缓存的接口,没用直接删
    proxy_cache_purge cache_one $1$is_args$args;
}
#proxy 
include proxy/temp.com/*.conf;  # 代理配置,完全多余,会覆盖或干扰向真实部署的后端资源访问

#PHP-INFO-START
include php/00.conf;  # PHP 解析配置,没装 PHP 环境直接删
#PHP-INFO-END

#REWRITE-START
include rewrite/temp.com/*.conf;  # 伪静态重写规则,会与try_files冲突,还有可能跳转旧域名
#REWRITE-END

#redirect 
include redirect/temp.com/*.conf; # 重定向配置,多余,后续要配置HTTPS的 SSL 证书才需要

📌 总结:可见宝塔生成的配置是针对通用场景的,大部分都没用,只需要精简到保留必要的配置项。


最终精简配置(参考)

server {
    listen 8081;                              # 换成合适的运行端口
    server_name xx.xx.xx.xx;                  # 换成真实域名
    root C:/wwwroot/xxxx/xxx;                 # 项目解析根目录
    index index.html;
    try_files $uri $uri/ /index.html;

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

    location /api/ {                          # API 反向代理
        proxy_pass http://127.0.0.1:8080/api/;    # 对应真实后端运行路径
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 屏蔽敏感文件
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md) {
        return 404;
    }
}

四、部署时最头疼的问题(重头戏)

踩坑 6:为何一直显示 Nginx 欢迎页

现象:部署后访问域名,始终显示 Nginx 欢迎页,无论怎么修改配置都没用。

排查过程

步骤 控制台命令 发现
检查端口监听 netstat -ano | findstr :8081 两个 Nginx 进程在监听 8081 端口(PID 6848 和 7992)
本地 file 协议验证 file:///C:/wwwroot/.../index.html 也是欢迎页 —— 彻底排除了 Nginx 配置问题
检查文件内容 notepad index.html 文件内容本身就是 Nginx 欢迎页的 HTML

根因

宝塔面板在创建新站点时,会自动向站点根目录写入一个默认的 index.html(即 Nginx 欢迎页),覆盖了上传的 Vue 构建产物。

解决

直接再次上传覆盖项目解析根目录 dist ,重启Nginx服务

💡提供一个通用的排查思路:

file://  协议直接从硬盘读取文件,完全不经过 Nginx。如果这都显示欢迎页,说明:

  • 文件内容本身就是 Nginx 欢迎页(被宝塔覆盖了)

  • 而不是 Nginx 配置或进程的问题


五、实践总结

正确部署顺序

  1. 本地npm run build 构建生产包

  2. 本地:检查 dist/ 目录结构(确认有 index.html 和 assets/

  3. 服务器:上传 dist/ 到目标目录(先上传文件,再建站点

  4. 宝塔:新建站点,根目录指向已上传的文件夹

  5. 宝塔:修改配置文件,精简到最简配置

  6. 宝塔:重启 Nginx

  7. 验证:访问域名测试


六、技术要点速查

知识点 说明
createWebHistory() Vue Router 的 History 模式,URL 不带 #,需要服务端配合
try_files $uri $uri/ /index.html Nginx SPA 回退规则,找不到文件时返回 index.html
vite-plugin-vue-devtools 开发工具插件,生产环境必须排除
netstat -ano | findstr :端口 Windows 查看端口监听和 PID
file:/// 协议 绕过服务器直接访问本地文件,用于区分是 Nginx 问题还是文件问题
宝塔默认站点机制 创建站点时会自动写入默认 index.html,建议先上传文件再建站

📝 最后吐槽:宝塔的“自动化”有时候反而成了坑,尤其是对于 静态 项目。希望这篇记录能帮到同样踩坑的朋友,少走弯路!

如果觉得有用,点个赞再走呗(👉゚ヮ゚)👉~ 

更多推荐