Vue 项目部署与 404 问题解决

Vue 项目部署流程及 history 模式下刷新 404 问题的原因和解决方案

问题

Vue 项目如何部署到服务器?使用 history 模式时,刷新页面为什么会出现 404 错误?

解答

部署流程

前后端分离模式下,前端部署只需将构建产物上传到服务器的静态资源目录。

1. 构建项目

npm run build

2. 上传构建产物

# 使用 scp 上传到服务器
scp dist.zip user@host:/var/www/html

3. 配置 Nginx

server {
  listen 80;
  server_name www.xxx.com;

  location / {
    root /data/dist;
    index index.html;
  }
}

4. 重启 Nginx

# 检查配置
nginx -t

# 重启服务
nginx -s reload

404 问题原因

为什么 history 模式会出现 404?

Vue 是单页应用(SPA),构建后只生成一个 index.html 文件。当访问 www.xxx.com/login 并刷新时:

  1. 浏览器向服务器请求 /login 路径
  2. Nginx 在服务器上找不到 login 这个文件
  3. 返回 404 错误

本质原因:路由切换由前端 JS 控制,但刷新时会向服务器发起真实请求。

为什么 hash 模式没问题?

hash 模式的 URL 如 www.xxx.com/#/login# 后面的内容不会发送到服务器。服务器只会收到 www.xxx.com 的请求,始终返回 index.html

解决方案

1. 配置 Nginx 重定向

将所有请求重定向到 index.html,让前端路由接管:

server {
  listen 80;
  server_name www.xxx.com;

  location / {
    root /data/dist;
    index index.html;
    try_files $uri $uri/ /index.html;
  }
}

2. 添加前端 404 页面

由于所有路径都返回 index.html,需要在前端处理无效路由:

const router = new VueRouter({
  mode: 'history',
  routes: [
    // 其他路由...
    { path: '*', component: NotFoundComponent }
  ]
})

3. 重启 Nginx

nginx -s reload

关键点

  • Vue 构建后只生成一个 index.html,所有路由由前端 JS 控制
  • history 模式刷新会向服务器请求真实路径,找不到文件就返回 404
  • hash 模式的 # 后内容不会发送到服务器,所以不会出现 404
  • 使用 try_files 将所有请求重定向到 index.html,交给前端路由处理
  • 配置通配符路由 path: '*' 处理前端的无效路径