这类项目最值得先看的不是功能列表,而是能不能在普通服务器环境里稳定跑起来。Vue3 + Nuxt4 做 SSR 网站,部署到 Ubuntu 服务器上,听起来是标准流程,但实际落地时,新手最容易卡在环境依赖、构建配置、进程管理和反向代理这几个环节。我一般会建议把第一次部署拆成三步:先把本地开发环境跑通,再在服务器上把基础环境配好,最后处理构建、启动和对外访问。下面按实际落地顺序拆一遍,重点不是命令本身,而是每个环节为什么这么做,以及卡住时先看哪里。
1. 先确认你的项目在本地能正常构建和启动 SSR
很多人一上来就在服务器上折腾,结果发现是项目本身在本地 SSR 模式下就跑不起来。所以第一步必须在本地验证。
1.1 检查项目结构和关键配置
打开你的 Vue3 + Nuxt4 项目,先看几个关键文件是否存在且配置正确。
package.json:确认nuxt的版本是^4.0.0或更高。同时检查scripts里是否有build和preview命令。一个典型的 Nuxt4 项目脚本配置如下:
{ "scripts": { "dev": "nuxt dev", "build": "nuxt build", "preview": "nuxt preview", "generate": "nuxt generate" } }nuxt.config.ts(或.js):这是核心配置文件。重点检查ssr选项是否设置为true(默认就是)。另外,如果你的应用需要监听特定端口或主机,可以在这里配置devServer或nitro(Nuxt 底层服务引擎)相关设置,但部署时通常由环境变量或进程管理器控制。.env或.env.production:检查生产环境变量,特别是NODE_ENV=production以及任何 API 基础地址。服务器环境和本地开发环境的不同,往往首先体现在环境变量上。
1.2 在本地执行构建和预览
在项目根目录下,按顺序执行以下命令,模拟生产环境:
# 1. 安装依赖(如果还没安装) npm install # 2. 执行生产构建 npm run build构建过程会生成.output目录,里面包含了 SSR 应用运行所需的所有服务端和客户端代码。如果构建失败,错误信息会直接输出在终端。常见构建失败原因包括:
- Node.js 版本不兼容:Nuxt4 通常需要 Node.js 18 或更高版本。用
node -v检查。 - 内存不足:构建大型项目可能消耗大量内存,如果本地内存不足,可能会报
JavaScript heap out of memory错误。 - 依赖安装问题:
node_modules混乱或网络问题导致包未正确安装。可以尝试删除node_modules和package-lock.json后重新npm install。
构建成功后,运行预览命令:
npm run preview这个命令会启动一个生产模式的服务器(通常基于.output目录),监听在某个端口(如http://localhost:3000)。用浏览器打开这个地址,确认页面能正常渲染,且是服务端渲染(查看网页源代码,能看到渲染好的 HTML 内容,而不是只有一个<div id="app">)。
如果本地预览都失败,先别急着上服务器。问题很可能出在项目代码、配置或依赖上,在本地解决成本更低。
2. 准备 Ubuntu 服务器:不只是安装 Node.js
假设你有一台干净的 Ubuntu 22.04 LTS 服务器。我们的目标不仅是装上 Node.js,还要建立一个稳定、可维护的运行环境。
2.1 系统更新与基础工具
通过 SSH 连接到你的服务器后,首先更新系统包列表并升级现有包:
sudo apt update sudo apt upgrade -y然后安装一些后续可能需要的工具,如用于解压、进程管理和网络调试的:
sudo apt install -y curl wget unzip htop net-tools2.2 安装 Node.js 和 npm(使用 NodeSource)
Ubuntu 默认仓库的 Node.js 版本可能较旧。更推荐使用 NodeSource 仓库安装长期支持版(LTS)。以安装 Node.js 20.x 为例:
# 下载并执行 NodeSource 安装脚本 curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - # 安装 Node.js 和 npm sudo apt install -y nodejs安装后验证版本:
node -v # 应输出 v20.x.x npm -v # 应输出对应的 npm 版本2.3 安装并配置 PM2(进程管理)
为什么不用npm run preview直接运行?因为它在终端关闭后进程就会结束,也不具备自动重启、日志管理、监控等功能。对于生产环境,PM2是更稳妥的选择。
全局安装 PM2:
sudo npm install -y pm2@latest -gPM2 安装后,可以将其设置为开机自启动,这样服务器重启后应用能自动恢复:
# 生成启动脚本(根据提示选择) pm2 startup # 执行上一条命令输出的指令(例如:sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your_username --hp /home/your_username) # 保存当前进程列表,以便开机恢复 pm2 save2.4 配置防火墙(如果启用)
如果服务器启用了 UFW(Uncomplicated Firewall),需要放行 SSH(22)、HTTP(80)和 HTTPS(443)端口:
sudo ufw allow ssh sudo ufw allow http sudo ufw allow https sudo ufw enable使用sudo ufw status检查规则。
3. 上传代码与服务器端构建
代码上传到服务器有多种方式,这里介绍两种常见且直接的方法。
3.1 方法一:通过 Git 克隆(推荐)
如果你的项目代码在 Git 仓库(如 GitHub, GitLab, Gitee),这是最方便的方式。
- 在服务器上安装 Git:
sudo apt install -y git - 克隆你的项目仓库:
cd /home/your_username git clone https://your-repository-url.git your-project-name cd your-project-name - 安装项目依赖并构建:
npm install --production # 仅安装生产依赖,速度更快 npm run build注意:服务器构建环境和本地必须一致。如果构建需要开发依赖(如某些类型检查工具),可能需要去掉
--production标志,或使用npm ci命令。
3.2 方法二:通过 SCP 或 SFTP 上传
如果项目未使用 Git,可以将本地构建好的.output目录和package.json等必要文件打包上传。
- 在本地项目目录,打包必要文件(假设在项目根目录):
# 打包除 node_modules 外的源码和配置文件 tar -czf deploy.tar.gz --exclude=node_modules --exclude=.git . - 使用 SCP 上传到服务器:
scp deploy.tar.gz your_username@your_server_ip:/home/your_username/ - 在服务器上解压并进入目录:
cd /home/your_username tar -xzf deploy.tar.gz -C your-project-name cd your-project-name npm install --production npm run build
关键点:无论哪种方式,务必在服务器上重新执行npm run build。因为构建产物(.output)可能包含与操作系统或 Node.js 版本相关的原生模块,本地(如 Windows/macOS)和服务器(Linux)环境不同,直接拷贝本地构建产物可能导致运行时错误。
4. 使用 PM2 启动和管理 Nuxt SSR 应用
构建完成后,.output目录里会有一个server目录,里面包含了 Nitro 服务器入口。我们需要告诉 PM2 如何启动它。
4.1 创建 PM2 生态系统配置文件
在项目根目录创建一个ecosystem.config.js文件:
module.exports = { apps: [ { name: 'your-nuxt-app', // 应用名称,便于 PM2 管理 script: 'node', // 使用 node 命令执行 args: '.output/server/index.mjs', // Nitro 服务器的入口文件 exec_mode: 'cluster', // 集群模式,充分利用多核CPU instances: 'max', // 根据 CPU 核心数启动最大实例数 autorestart: true, // 应用崩溃时自动重启 watch: false, // 生产环境不建议开启监听文件变化 max_memory_restart: '1G', // 内存超过 1G 自动重启 env: { NODE_ENV: 'production', HOST: '0.0.0.0', // 监听所有网络接口 PORT: 3000, // 应用运行端口,可自定义 }, }, ], };这个配置做了几件重要的事:
- 指定入口:明确告诉 PM2 启动哪个文件。
- 集群模式:
cluster模式可以启动多个应用实例,由 PM2 做负载均衡,提升并发处理能力。 - 资源限制:
max_memory_restart可以防止内存泄漏导致服务器崩溃。 - 环境变量:在这里集中管理生产环境变量,比在系统层面设置更清晰。
4.2 启动应用并管理
在项目根目录下,使用 PM2 启动应用:
pm2 start ecosystem.config.js启动后,可以使用以下命令进行管理:
pm2 status # 查看所有应用状态 pm2 logs your-nuxt-app # 查看实时日志 pm2 logs your-nuxt-app --err # 只看错误日志 pm2 restart your-nuxt-app # 重启应用 pm2 stop your-nuxt-app # 停止应用 pm2 delete your-nuxt-app # 从 PM2 列表中删除应用现在,你的 Nuxt SSR 应用应该已经在服务器的 3000 端口运行了。可以在服务器内部用curl http://localhost:3000测试是否返回 HTML。
5. 配置 Nginx 反向代理和域名访问
直接通过 IP:3000 访问不专业,也不安全(无法使用 HTTPS)。我们需要用 Nginx 作为反向代理,将 80/443 端口的请求转发到本地的 3000 端口。
5.1 安装 Nginx
sudo apt install -y nginx5.2 配置站点
删除默认配置,为你的站点创建一个新的配置文件:
sudo rm /etc/nginx/sites-enabled/default sudo nano /etc/nginx/sites-available/your-domain.conf将以下配置粘贴进去(将your_domain.com替换为你的域名,your_server_ip替换为服务器公网 IP):
server { listen 80; listen [::]:80; server_name your_domain.com www.your_domain.com; # 静态文件缓存(可选,提升性能) location /_nuxt/ { alias /home/your_username/your-project-name/.output/public/_nuxt/; expires 1y; add_header Cache-Control "public, immutable"; } location / { proxy_pass http://localhost:3000; # 指向 PM2 运行的端口 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; 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_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; # 以下两行对 Nuxt SSR 很重要,确保能获取到真实客户端 IP 和协议 proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; } }关键配置解释:
proxy_pass:将所有请求转发到本地 3000 端口的 Nuxt 应用。proxy_set_header:这些头部信息确保了 Nuxt 应用能接收到原始客户端的 IP、协议等信息,对于日志记录和某些中间件功能至关重要。location /_nuxt/:这是 Nuxt 构建生成的客户端静态资源(JS、CSS)路径。通过 Nginx 直接提供这些文件,效率远高于经过 Node.js 处理,并可以设置长期缓存。
5.3 启用配置并测试
创建符号链接以启用站点配置,并测试 Nginx 配置语法:
sudo ln -s /etc/nginx/sites-available/your-domain.conf /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置,应显示 “syntax is ok” 和 “test is successful”如果测试成功,重启 Nginx 使配置生效:
sudo systemctl restart nginx5.4 配置域名解析和 SSL(HTTPS)
- 域名解析:在你的域名注册商处,将域名
A记录指向你的服务器公网 IP。 - 安装 Certbot 获取 SSL 证书:
Certbot 会自动修改你的 Nginx 配置,添加 HTTPS 支持并设置自动续期。sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d your_domain.com -d www.your_domain.com
完成以上步骤后,你应该可以通过https://your_domain.com访问到部署好的 Vue3 + Nuxt4 SSR 网站了。
6. 部署后的监控、维护与常见问题排查
部署上线只是开始,后续的稳定运行更需要关注。
6.1 基础监控与日志
- PM2 监控:
pm2 monit命令可以打开一个仪表板,实时查看 CPU、内存占用。 - 日志管理:PM2 日志默认在
~/.pm2/logs/目录。定期检查或使用日志轮转工具(如pm2-logrotate)管理。 - 服务器资源:使用
htop或glances监控整体服务器资源。
6.2 自动化部署脚本(简易版)
每次更新代码都手动操作太繁琐。可以在项目根目录创建一个简单的部署脚本deploy.sh:
#!/bin/bash echo “开始拉取最新代码...” git pull origin main echo “安装依赖...” npm install --production echo “构建项目...” npm run build echo “重启应用...” pm2 restart ecosystem.config.js echo “部署完成!”给脚本执行权限:chmod +x deploy.sh。以后更新时,只需在服务器项目目录下运行./deploy.sh即可。
6.3 常见问题与排查顺序
当网站无法访问或出现错误时,按以下顺序排查:
检查应用进程状态:
pm2 status查看应用是否为
online状态。如果是errored或stopped,查看错误日志:pm2 logs your-nuxt-app --err。检查端口监听:
sudo netstat -tlnp | grep :3000确认 3000 端口是否有进程在监听。如果没有,PM2 可能启动失败。
检查 Nginx 状态和错误日志:
sudo systemctl status nginx sudo tail -f /var/log/nginx/error.log确认 Nginx 运行正常,并查看是否有访问或代理错误。
检查防火墙和安全组:
- 服务器本地防火墙(UFW):
sudo ufw status - 云服务商安全组规则:确保 80 和 443 端口对公网开放。
- 服务器本地防火墙(UFW):
检查资源占用:
free -h # 查看内存 df -h # 查看磁盘空间内存或磁盘空间不足会导致应用崩溃或构建失败。
检查项目本身:
- 回退到上一个稳定版本,确认是否是本次代码更新引入的问题。
- 在服务器上直接运行
node .output/server/index.mjs,看是否有更直接的错误输出。
一个典型坑点:环境变量。确保服务器上的环境变量(如数据库连接字符串、API密钥)与本地不同且正确。PM2 的ecosystem.config.js中的env区块是设置它们的好地方。
我个人更建议先把单机部署这套流程跑稳,包括代码更新、进程重启和日志查看。这套组合(Nuxt4 + PM2 + Nginx)对于中小型 SSR 应用已经足够稳定。如果后续流量增长,再考虑容器化(Docker)、CI/CD 流水线或者更复杂的负载均衡方案。