Vue项目三步部署指南:Ubuntu + Nginx从构建到线上发布

📅 发布时间:2026/10/17 17:28:11
Vue项目三步部署指南:Ubuntu + Nginx从构建到线上发布
看到标题里的“ubnutu”我先说个小事这应该是 ubuntu 的笔误。不过这并不影响思路下面我统一用 ubuntu 22.04 来讲。很多前端同学开发完 vue 项目npm run build 一执行dist 目录出来了然后就卡住了——接下来该干嘛有人拿 dist 直接丢给后端有人压缩包发给运维还有人复制粘贴到服务器结果打开全是白屏。这篇文章就把这个过程收敛成清清楚楚的三步本地构建、安装 nginx、上传配置站点。目标只有一个让你在自己电脑上敲完命令浏览器里能稳定访问到线上页面。我会把每一步的命令、参数、为什么这么做全部讲透最后再给你一份高频问题排查清单。不管你是第一次接触服务器部署的前端新人还是想自己搞定发布流程的全栈开发者照着这篇文章操作就能把项目干净利落地跑起来。1. 部署思路复盘vue 项目到底部署了什么以及为什么是 nginx1.1 构建产物的本质决定了部署方式很多人第一次部署 vue 项目时会有一个误区以为要把整个项目源码传到服务器上然后在服务器上 npm install、npm run dev。这是把“开发模式”和“生产模式”搞混了。vue 是典型的单页应用SPA开发时依赖 node 环境跑 dev server但用户真正访问的是编译压缩后的静态资源一个 index.html、一堆 js 和 css 文件。所以部署的本质其实非常简单把 npm run build 生成的 dist 目录里的文件交给一个 Web 服务器去托管让用户通过 http 请求拿到这些静态文件。打个比方dist 目录是一桌已经做好的菜nginx 是替你把菜端到客人面前的服务员。你不需要在服务器上重新炒菜只需要把菜放上餐台并且告诉服务员“客人要点哪道菜时该往哪个窗口取”。理解这一点之后后面所有的操作都会变得顺理成章构建这个动作发生在本地上传动作负责搬运nginx 负责对外提供服务仅此而已。1.2 为什么选 nginx而不是 Apache 或其他方案部署静态网站的可选项其实不少我帮你把主流的几个拉出来对比一下Web 服务方案静态文件性能反向代理配置内存占用学习成本适用场景nginx极高高并发下稳定简洁直观低约几 MB 到几十 MB低静态站点 反向代理中小项目首选Apache良好但高并发下更吃内存配置冗长较高中老牌系统兼容模块多Node 直接托管一般取决于业务逻辑需要自己写代码高中纯 Node 服务、前后端同构云对象存储静态托管极高有限依赖平台无服务器概念低纯静态站点、或有 CDN 需求的项目nginx 在静态文件服务这个场景下几乎是碾压级的优势。它不是靠什么魔法而是基于事件驱动的异步架构一个进程能挂住大量并发连接内存占用却很小。再加上配置语法走的是声明式路线写一个 server 块就能搞定虚拟主机、反向代理、缓存、gzip 压缩这些需求不需要像 Apache 那样维护一堆钩子模块。对个人项目和中小团队来说nginx 就是那个性价比最高的服务员。1.3 为什么选 ubuntu 22.04 作为服务器系统ubuntu 22.04 是 LTS 版本意味着有长期安全更新和维护周期系统稳定性有保障。它的 apt 包管理器让安装软件变得非常简单一条 apt install nginx 就能装完不需要像编译源码那样折腾依赖。另外ubuntu 的服务器生态非常成熟几乎你能遇到的部署问题都有人在网上分享过排查经验。这套组合拳打下来对于想要快速跑通部署流程的开发者来说是最省心的起点。2. 动手前先摸清三个关键细节路由模式、环境变量、服务器初始状态2.1 路由模式决定服务器要不要“兜底”vue-router 有两种路由模式hash 模式和 history 模式。默认开发环境下很多脚手架会直接用 createWebHashHistory地址栏里会出现一个 # 号。比如 http://example.com/#/home。这种模式下的路由变化其实是在改 # 后面的部分浏览器不会真正向服务器发起新的页面请求所以刷新页面时 nginx 根本感知不到也就不会出现 404。这就是很多新手第一次部署没遇到问题的原因。但生产环境大家通常会用 createWebHistory因为地址栏干净、美观也更符合用户认知。问题在于当用户直接访问 http://example.com/home 时浏览器会把这个地址当作一个真实路径发给 nginx。nginx 在磁盘上找 home 这个文件或目录结果当然找不到于是默认返回 404。解决办法是在 nginx 配置里加一行 try_files把请求统一回退到 index.html。这个行为的本质是告诉 nginx如果磁盘上找不到对应文件就把这个请求交给前端路由去处理让 vue-router 自己判断应该渲染哪个页面。听起来很绕但配起来就一行后面第三章会给出完整配置。这个细节是整个部署过程中新手最容易踩的坑我建议你在构建项目之前就先确认自己用的是哪种模式。2.2 环境变量和接口地址的坑vue 项目里通常会有 .env.development 和 .env.production 两个文件里面定义了 VITE_API_BASE_URL 或类似的环境变量。本地开发时请求的是 http://localhost:8080/api这是开发服务器的地址但打包后的生产代码必须指向线上后端地址比如 https://api.example.com。如果你在代码里硬编码了接口地址或者 .env.production 里的值没配对就会出现一个非常隐蔽的问题页面能打开界面也正常渲染但所有请求都打到本地开发地址上最终一片报错。我见过不少同学把接口地址直接写死在业务代码里每次部署不同环境就要改代码、重新打包费时费力还容易出错。正确做法是一开始就区分环境变量打包时脚手架会自动读取 .env.production 里的值并注入代码。还有一个小细节打包完成后你可以打开 dist 目录下的 js 文件搜索一下你的接口域名肉眼确认是否被正确替换进去了。这一步只需要几秒钟却能帮你提前发现一半以上的部署事故。2.3 服务器初始状态检查清单在开始安装之前先在服务器上确认三件事。第一nginx 是否已经存在。有些云服务器镜像预装了 nginx重复安装会报错或者引入版本冲突用 nginx -v 看一下就知道。第二80 端口是否被占用。服务器上如果有其他 Web 服务占了 80nginx 启动时会遇到 bind() failed 的报错。用 ss -tlnp | grep :80 检查如果有进程占用了你得先搞清楚它是干什么的别贸然杀掉。第三当前用户是否有 sudo 权限。部署过程中大量命令需要 root 权限如果你只有普通账号且没有 sudo后面会非常被动。这三件事花不了两分钟但能避免后续所有操作都卡在半道上。我把检查命令写在一起你在 ssh 登录服务器后直接复制执行即可。nginx -v 2/dev/null || echo nginx 未安装 ss -tlnp | grep -E :(80|443) || echo 80/443 端口未占用 sudo -v echo 当前用户有 sudo 权限3. 三步部署实操从本地构建到 nginx 线上发布3.1 第一步本地构建 vue 项目拿到 dist 产物部署流程的第一步其实不在服务器上而是在你自己的电脑上完成。打开项目根目录先确认 node 环境没问题再安装依赖并构建。你可以在本地打开终端依次执行以下几个命令。node -v npm -v npm install npm run buildnode -v 这一步很多人会跳过但它其实值得看一眼。vue 3 的脚手架一般要求 node 版本在 18 以上如果你本地装的是老版本 nodenpm install 过程中可能报错构建出来的资源也可能存在兼容性问题。遇到版本不符时建议先升级 node而不是在项目里强行绕过。npm install 执行完毕后npm run build 会把项目编译输送到 dist 目录。构建完成后你用 ls 看一下 dist 目录里有什么。ls -la dist正常情况下你会看到 index.html 和一个 assets 目录assets 里面是编译压缩后的 js、css、图片等静态资源。有些项目配置了 public 目录里面的内容也会原样拷贝到 dist 根目录。这里有一个确认点index.html 必须存在于 dist 的根路径因为 nginx 默认会在这个位置寻找入口页面。如果构建产物路径不对后面配置 nginx 时要调整 root 路径但最简单的情况就是让 dist 目录作为网站的根目录。构建完成以后你可以在本地先启动一个临时静态服务器亲眼验证一下产物能否正常访问。npx serve dist浏览器打开终端提示的地址如果页面正常渲染、接口正常请求说明构建产物本身没有问题。这一步能帮你把“前端代码问题”和“服务器配置问题”隔离开后面万一出现故障排查范围会小很多。本地验证有问题时先别急着部署因为部署只能把问题从一台机器搬到另一台机器不会解决问题。3.2 第二步安装并启动 nginx接下来切换到服务器操作。ubuntu 22.04 安装 nginx 非常简单我直接把命令完整列出来。sudo apt update sudo apt install nginx -yapt update 的作用是刷新软件源索引避免安装到过期版本。安装完成后nginx 会作为系统服务存在默认已经启动。执行下面这条命令确认服务状态。sudo systemctl status nginx如果你看到输出里带有 active (running) 的字样说明 nginx 服务在正常运行。如果没启动可以用 sudo systemctl start nginx 手动拉起来。我还建议顺手执行 sudo systemctl enable nginx让 nginx 在服务器重启之后自动启动。这一步很不起眼但能避免服务器意外重启后网站静悄悄挂掉的情况属于典型的花一分钟省一小时的操作。安装完成后先了解 nginx 的几个关键目录和文件因为后面所有操作都会围绕它们展开。主配置文件是 /etc/nginx/nginx.conf它负责加载其他配置站点配置文件通常放在 /etc/nginx/sites-available/ 目录下要启用的站点则在 /etc/nginx/sites-enabled/ 目录下创建软链接。这种“available 存配置、enabled 启用配置”的结构让你在维护多个站点时可以提前准备配置等需要上线时再一键启用非常灵活。如果你此时直接在浏览器输入服务器 IP看到的将是 nginx 默认的欢迎页面。这是 nginx 自带默认站点生效的结果。访问成功说明 nginx 已经对外提供服务整个部署工具链是通的接下来就可以替换默认站点换成我们自己的 vue 项目。3.3 第三步上传 dist 并在 nginx 里配置站点先把第一步构建好的 dist 目录上传到服务器。常用的方式有两种第一种是 scp简单直接。scp -r dist/* 用户名你的服务器IP:/var/www/项目名/第二种是 rsync增量同步更高效适合文件多、经常更新的场景。rsync -av --delete dist/ 用户名你的服务器IP:/var/www/项目名/我个人更推荐 rsync因为 --delete 参数能让服务器上多余的文件自动清理掉确保线上文件和本地构建产物完全一致。注意目录路径的选择我习惯把站点文件放在 /var/www/ 下面以项目名作为子目录。你也可以按自己的习惯放在 /home/用户名/sites/ 下关键是 nginx 配置里的 root 路径要和文件实际存放的位置完全一致。上传命令里的 /var/www/项目名/ 需要你先在服务器上创建好目录。可以执行sudo mkdir -p /var/www/项目名创建完成后接下来是核心环节编写 nginx 站点配置。用文本编辑器新建一个配置文件sudo vim /etc/nginx/sites-available/vue-project.conf然后把下面的配置内容写进去。这个配置是我用过的最小可用版本每一步都有明确目的。server { listen 80; server_name yourdomain.com; root /var/www/项目名; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }我来逐行解释这个配置的含义。listen 80 表示监听 80 端口这是 HTTP 默认端口。server_name 填你的域名如果没有域名可以直接填服务器 IP效果一样。root 指向 dist 文件上传的目录nginx 会从这里读取静态文件。index index.html 指定目录访问时默认加载的入口文件。location / 块是所有请求的默认归宿。try_files $uri $uri/ /index.html 这一行是 history 路由模式能否正常刷新的关键。它的逻辑是先按请求路径找真实文件比如访问 /favicon.ico 时找到就返回再按目录找比如访问 /about 时看看有没有 about 目录如果都找不到就回退返回 index.html把请求交给前端路由去处理。location /api/ 块是反向代理的配置。前端项目通常会向后端发请求如果后端服务跑在同一台服务器的 8080 端口那么这个配置会把所有以 /api/ 开头的请求转发到后端服务。proxy_set_header 几行是为了让后端服务能拿到真实的客户端信息一般建议保留。写完配置后保存文件然后建立软链接启用这个站点配置并移除默认站点。sudo ln -s /etc/nginx/sites-available/vue-project.conf /etc/nginx/sites-enabled/ sudo rm /etc/nginx/sites-enabled/default然后检查配置语法这一步千万不能省。sudo nginx -t如果输出中出现 syntax is ok 和 test is successful说明配置语法没问题可以放心重新加载。如果出现错误nginx 会提示具体的行号根据提示修改后重新检查。最后重新加载 nginx让新配置生效sudo systemctl reload nginx到这里三步部署已经全部完成。你在浏览器里输入域名或服务器 IP应该就能看到 vue 项目正常渲染。为了确认服务端确实返回了页面可以执行 curl -I yourdomain.com返回的 HTTP 状态码如果是 200说明站点对外访问正常。4. 部署后常见维护与排查实录4.1 刷新页面 404问题通常出在 try_files最大概率出现的坑就是前面反复提到的 history 模式刷新 404。你在浏览器里访问首页没问题点击内部路由跳转也没问题但只要刷新一下当前的路由页面比如刷新 /user/list就会报 404 Not Found。原因我已经解释过浏览器把 /user/list 当作真实路径发给 nginxnginx 在 root 目录下找不到这个名字的文件就返回了 404。解决办法就是确认配置里有 try_files $uri $uri/ /index.html; 这一行。配置文件改完后执行 nginx -t 检查语法再 reload nginx刷新问题就会消失。这个坑我几乎每次给团队做部署培训都会遇到而且很多人一开始根本想不到是 nginx 配置的问题以为是 vue-router 代码写错了。如果你也遇到刷新 404先不要改代码回到 nginx 配置里找 try_files。4.2 页面白屏控制台报各种资源加载失败白屏问题一般发生在部署初期页面打开后一片空白打开浏览器开发者工具Console 里会出现一堆资源的 404 错误。常见原因有两个一是 index.html 里引用的 js、css 路径缺失二是构建时 base 配置没设对导致资源路径以绝对路径开头。如果你的项目部署在域名的根目录ajax 不需要特殊处理。但如果你把项目放在二级目录下比如 http://example.com/admin/就必须在 vite.config.js 里把 base 设置为相对路径或者 /admin/。路径配置不对index.html 引用的资源路径就会指向错误的地址nginx 自然找不到。解决方法是重新构建或在 nginx 配置里调整 root 路径的层级让资源请求能正确映射到 dist 目录下的 assets 文件。另外还可能是 dist 上传不完整比如你上传时漏掉了 assets 目录。用 du -sh /var/www/项目名 和本地 du -sh dist 对比一下体积能快速确认文件是否传齐。4.3 接口请求 502 或 504问题往往不在 nginx页面能打开但数据加载不出来打开控制台发现 /api/ 开头的请求返回 502 Bad Gateway。502 表示 nginx 无法从后端服务获取有效响应最常见的解释是后端服务根本没启动或者没有监听在你在 proxy_pass 里指定的端口上。先确认后端进程是否存活。如果后端是 node 服务执行 ss -tlnp | grep 8080 看看端口有没有被监听。如果服务没起来就回到后端启动步骤排查如果端口在监听但仍返回 502多半是后端服务跑了但没绑定在 127.0.0.1 上。有些后端框架默认只监听 IPv6 的 ::1nginx 通过 127.0.0.1 访问就会失败。504 Gateway Timeout 则是请求超时。如果后端接口本身耗时长比如跑复杂报表或调用外部服务可能在默认 60 秒内没响应。可以在 nginx 配置里增加 proxy_read_timeout 和 proxy_connect_timeout 来延长等待时间但不能无限拉长更根治的办法是优化后端接口的响应速度。4.4 403 Forbidden权限问题的一次典型排查nginx 返回 403 通常是因为它对请求的文件没有读权限或者目录索引被禁止。ubuntu 上 nginx 的工作进程一般以 www-data 用户运行如果 dist 文件的所有者是 root并且权限是 700www-data 用户根本进不去目录自然无法读取文件。遇到 403第一步看日志。/var/log/nginx/error.log 会明确告诉你 permission denied 出现在哪个路径。然后根据日志提示修复权限sudo chown -R www-data:www-data /var/www/项目名 sudo chmod -R 755 /var/www/项目名chown 把目录所有权交给 www-datachmod 给目录设置 755 权限让用户可以读取和执行。这一步操作完再刷新一般就能正常访问。需要提醒的是如果你用 ftp 或用 root 上传文件上传完成后记得顺手执行一次权限修正避免下次再踩同一个坑。4.5 修改代码后线上页面不变多半是缓存惹的祸部署新版本后用户浏览器里看到的还是旧页面这种问题也非常常见。核心原因是浏览器和 nginx 都会对静态资源做缓存。vue 脚手架默认打包时文件名会带上内容哈希比如 app.a1b2c3.js。文件内容变了哈希也会变理论上浏览器会请求新资源但入口 index.html 本身经常被浏览器缓存导致页面还在引用旧文件的路径。排查时你可以用 curl 看一下服务器返回的 index.html 内容是否已经更新curl -s http://yourdomain.com/ | grep -o app\.[a-z0-9]*\.js如果返回的确实是新文件名说明服务器没问题是浏览器缓存。这时可以强制刷新试一下。如果想让发布更顺滑可以做两件事一是在 nginx 配置里给 index.html 设置 no-cache 响应头让浏览器每次重新验证这个文件二是给带哈希的 js、css 设置较长的 expires 时间充分利用缓存减少加载时间。这两条配置在后续执行中我也会附上属于进阶优化但很值得提前配置好。4.6 配置文件常见语法错误自查新手手写 nginx 配置时经常会漏分号、多括号。nginx -t 就是帮你找出这些问题的工具。输出提示 unexpected end of file 时大多数人都是少了闭合大括号提示 unknown directive 时一般是上一行末尾漏了分号。我把两个高频错误点列出来你可以对照自查server 块、location 块以{开始必须以}结束每一个{都需要对应一个}。每行指令结尾必须带分号否则 nginx 会把下一行指令名当作参数解析直接报错。listen、server_name、root、index、try_files 这些指令都是分号结尾的。改完配置后我建议养成“三步检查”习惯先 nginx -t 检查语法再 systemctl reload nginx 加载配置最后 curl 一下域名确认返回 200。三步全过才算真的发布成功。5. 从一次部署到长期省心脚本、自检清单与我的体会5.1 把重复流程固化成部署脚本三次部署之后你就会发现整个流程里最耗时的是输入重复命令、担心漏步骤。这时候最好的朋友就是脚本。把构建和发布流程写成一个本地执行的 shell 脚本每次只需要跑一条命令就能完成发布。一个最小可用的 deploy.sh 大概长这样#!/bin/bash set -e echo 开始构建... npm run build echo 上传 dist 到服务器... rsync -av --delete dist/ 用户名你的服务器IP:/var/www/项目名/ echo 重新加载 nginx 配置... ssh 用户名你的服务器IP sudo nginx -t sudo systemctl reload nginx echo 发布完成当前可用版本已上线set -e 的作用是脚本中任意命令失败就立即终止避免明明构建失败了却继续上传旧版本。加了这行之后你不需要在终端前一直盯着输出构建失败会有明确提示不会出现“版本没更新但你还不知道”的尴尬。脚本执行前别忘了给权限chmod x deploy.sh。之后每次发布只需要 ./deploy.sh 一条命令。如果你想要更稳妥还可以在脚本里加一个远程 curl 检查确认线上版本号已经更新。这一套下来发布动作就从手动流水线变成了自动化指令。5.2 我自己的上线前自检清单经验贴里最值钱的部分往往是那些“提醒自己别犯错”的清单。我习惯在每次部署前按顺序过一遍下面这几项全过之后再宣布上线检查项检查方法或标准构建是否成功本地执行 npm run build 退出码为 0dist 目录存在环境变量是否生效grep 接口域名 检查 dist 内 js 文件确认没有本地地址残留文件是否完整上传rsync 日志无异常服务器 dist 体积与本地基本一致nginx 配置语法nginx -t 返回 syntax is oknginx 是否重新加载systemctl reload nginx 执行成功线上首页是否 200curl -I http://域名 返回 200页面刷新是否正常手动刷新一个 history 路由页面确认不 404接口是否正常返回浏览器里确认接口请求状态码和返回数据这个清单不是给别人看的是给自己兜底的。哪怕只是改了一行文案我也不会跳过全部流程因为我踩过太多次“改动很小所以不检查结果环境变量被覆盖导致发布事故”的坑。把检查成本降到最低的才是好流程脚本负责执行清单负责兜底两个配合心里踏实。5.3 我个人在实际操作中的体会是部署这条路刚开始会觉得难又是服务器又是 nginx 又是端口权限脑子里一团浆糊。但拆成“构建、装服务、传文件配站点”这三步以后每一步都变得可以被验证构建看 dist 目录里的 index.html 是否存在装服务看 systemctl status 是否为 running上传配站点看 curl 是否 200。用可验证的结果去驱动操作理解自然就上来了。最后再分享一个小技巧遇到任何部署问题先去看 nginx 的错误日志路径在 /var/log/nginx/error.log。这里记录着 90% 以上问题的根因比你盲目改配置高效得多。你可以在部署期间的终端里执行 tail -f /var/log/nginx/error.log 盯着日志一边操作一边观察很多问题会当场原形毕露。先跑通最简单的三步再慢慢往里面加 HTTPS、CDN、自动化部署这些进阶能力你会发现整个部署体系其实没有想象中那么复杂。