{T}

SSR项目部署实战

SSR项目部署实战

学习目标:掌握 Node.js 环境安装、PM2 进程管理、NestJS 部署、Nuxt.js 部署、PM2 配置文件、环境变量配置。


一、SSR 项目部署概述

1.1 SSR 部署核心要点

code
SSR 项目部署核心要点:
│
├── 1. 环境准备 
│   ├── 安装 Node.js(推荐 NVM)
│   ├── 安装 PM2
│   ├── 安装 Nginx(反向代理)
│   └── 配置数据库连接
│
├── 2. 项目构建 
│   ├── NestJS:npm run build → dist 目录
│   ├── Nuxt.js:npm run build → .output 目录
│   ├── 配置生产环境变量
│   └── 优化构建参数
│
├── 3. 文件上传 
│   ├── 上传构建产物
│   ├── 上传 package.json
│   ├── 上传依赖锁定文件
│   └── 上传环境配置文件
│
├── 4. 依赖安装 
│   ├── 安装生产依赖
│   ├── 配置国内镜像源
│   └── 解决依赖问题
│
├── 5. 进程管理 
│   ├── PM2 启动应用
│   ├── PM2 集群模式
│   ├── PM2 配置文件
│   └── PM2 开机自启
│
└── 6. 反向代理 
    ├── Nginx 配置
    ├── 负载均衡
    ├── SSL 配置
    └── 域名绑定

1.2 SSR 部署流程图

code
SSR 项目部署完整流程:
│
├── 第一步:准备服务器环境
│   ├── 安装 Node.js(使用 NVM)
│   ├── 配置 NVM 默认版本
│   ├── 安装 PM2(全局安装)
│   └── 安装 Nginx
│
├── 第二步:构建项目
│   ├── 配置生产环境变量
│   ├── 优化构建参数(关闭 sourceMap、开启 minify)
│   ├── 执行构建命令
│   └── 检查构建产物
│
├── 第三步:上传文件
│   ├── 上传构建产物(dist 或 .output)
│   ├── 上传 package.json
│   ├── 上传依赖锁定文件(pnpm-lock.yaml)
│   ├── 上传配置文件(.npmrc、.env)
│   └── 验证文件完整性
│
├── 第四步:安装依赖
│   ├── 配置国内镜像源
│   ├── 安装 PM2(如果未安装)
│   ├── 安装项目依赖
│   └── 验证依赖安装成功
│
├── 第五步:配置环境变量
│   ├── 修改数据库连接配置
│   ├── 配置 API 地址
│   ├── 配置端口
│   └── 验证配置正确
│
├── 第六步:启动应用
│   ├── 测试启动(node 命令)
│   ├── PM2 启动应用
│   ├── 配置 PM2 集群模式
│   └── 配置开机自启
│
└── 第七步:配置 Nginx
    ├── 配置反向代理
    ├── 配置负载均衡
    ├── 配置 SSL/HTTPS
    └── 重启 Nginx

二、Node.js 环境安装(NVM)

2.1 NVM 简介

code
NVM(Node Version Manager)简介:
│
├── 什么是 NVM
│   ├── Node.js 版本管理工具
│   ├── 可以安装多个 Node.js 版本
│   ├── 可以随时切换 Node.js 版本
│   └── 推荐:生产环境使用 NVM
│
├── 为什么使用 NVM
│   ├── 方便安装和管理 Node.js 版本
│   ├── 可以快速切换不同版本
│   ├── 适合多项目多版本场景
│   └── 便于团队协作
│
└── NVM 常用命令
    ├── nvm install <version>:安装指定版本
    ├── nvm use <version>:使用指定版本
    ├── nvm ls:查看已安装版本
    ├── nvm ls-remote:查看远程可用版本
    ├── nvm alias default <version>:设置默认版本
    └── nvm current:查看当前使用版本

2.2 安装 NVM

方式一:官方脚本安装(国外服务器)

bash
#  下载并安装 NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# 或使用 wget
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

方式二:使用国内镜像安装(国内服务器)

bash
#  使用 Gitee 镜像
curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash

# 或使用 wget
wget -qO- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash

安装后配置

bash
#  使 NVM 立即生效
source ~/.bashrc

#  验证安装
nvm --version
# 输出:0.39.0

安装脚本做了什么

code
NVM 安装脚本执行内容:
│
├── 第一步:下载 NVM 仓库
│   └── 克隆到 ~/.nvm 目录
│
├── 第二步:配置环境变量
│   └── 在 ~/.bashrc 中添加 NVM 配置
│
├── 第三步:配置 NVM 环境变量
│   ├── export NVM_DIR="$HOME/.nvm"
│   ├── [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
│   └── [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
│
└── 第四步:使配置生效
    └── 需要手动执行 source ~/.bashrc

2.3 安装 Node.js

安装 Node.js LTS 版本

bash
#  查看远程可用版本
nvm ls-remote

#  安装 Node.js 18.x LTS
nvm install 18.16.0

#  查看已安装版本
nvm ls

#  使用指定版本
nvm use 18.16.0

#  设置默认版本
nvm alias default 18.16.0

#  验证安装
node -v    # v18.16.0
npm -v     # 9.x.x

配置默认版本

bash
#  方式一:使用 nvm alias
nvm alias default 18.16.0

#  方式二:修改配置文件
vi ~/.bash_profile

# 添加以下内容
source ~/.bashrc
nvm use default

# 使配置生效
source ~/.bash_profile

配置国内镜像源

bash
#  配置 NVM 镜像源
export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node

#  配置 npm 镜像源
npm config set registry https://registry.npmmirror.com

#  或使用 cnpm
npm install -g cnpm --registry=https://registry.npmmirror.com

三、PM2 进程管理

3.1 PM2 安装

bash
#  全局安装 PM2
npm install -g pm2

# 或使用 cnpm 安装(国内)
cnpm install -g pm2

#  验证安装
pm2 --version
# 输出:5.3.0

#  查看 PM2 帮助
pm2 --help

3.2 PM2 基础命令

code
PM2 基础命令速查:
│
├── 启动应用
│   ├── pm2 start app.js:启动应用
│   ├── pm2 start app.js --name my-app:启动并命名
│   ├── pm2 start app.js -i max:集群模式启动
│   ├── pm2 start ecosystem.config.js:使用配置文件启动
│   └── pm2 start app.js --env production:指定环境变量
│
├── 管理应用
│   ├── pm2 stop my-app:停止应用
│   ├── pm2 restart my-app:重启应用
│   ├── pm2 delete my-app:删除应用
│   ├── pm2 reload my-app:重载应用(零停机)
│   └── pm2 kill:杀死所有进程
│
├── 查看应用
│   ├── pm2 list:查看所有应用
│   ├── pm2 show my-app:查看应用详情
│   ├── pm2 describe my-app:查看应用详细信息
│   └── pm2 monit:监控面板
│
├── 查看日志
│   ├── pm2 logs:查看所有日志
│   ├── pm2 logs my-app:查看指定应用日志
│   ├── pm2 flush:清空日志
│   └── pm2 reloadLogs:重载日志
│
└── 开机自启
    ├── pm2 startup:生成开机自启命令
    ├── pm2 save:保存当前应用列表
    └── pm2 unstartup:取消开机自启

3.3 PM2 启动模式

code
PM2 启动模式对比:
│
├── Fork 模式(单进程)
│   ├── 命令:pm2 start app.js
│   ├── 特点:单进程运行
│   ├── 适用:简单应用、开发环境
│   └── 缺点:无法利用多核 CPU
│
└── Cluster 模式(集群)
    ├── 命令:pm2 start app.js -i max
    ├── 特点:多进程运行、自动负载均衡
    ├── 适用:生产环境、高并发场景
    └── 优点:充分利用多核 CPU、提高性能 

Cluster 模式详解

bash
#  启动最大 CPU 核心数个进程
pm2 start app.js -i max

#  启动指定数量进程
pm2 start app.js -i 4

#  使用配置文件
# ecosystem.config.js
module.exports = {
  apps: [{
    name: 'my-app',
    script: './app.js',
    instances: 'max',      # 最大 CPU 核心数
    exec_mode: 'cluster',  # 集群模式
  }]
}

3.4 PM2 配置文件

创建配置文件

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'my-app',                    // 应用名称
      script: './dist/main.js',          // 入口文件
      
      //  进程配置
      instances: 'max',                  // 进程数量:max | 数字
      exec_mode: 'cluster',              // 执行模式:fork | cluster
      watch: false,                      // 是否监听文件变化
      max_memory_restart: '1G',          // 内存达到 1G 自动重启
      
      //  环境变量
      env: {
        NODE_ENV: 'development',
        PORT: 3000,
      },
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
        BASE_URL: 'http://192.168.31.77:3000',
      },
      
      //  日志配置
      error_file: './logs/err.log',      // 错误日志
      out_file: './logs/out.log',        // 输出日志
      log_date_format: 'YYYY-MM-DD HH:mm:ss', // 日志日期格式
      
      //  其他配置
      merge_logs: true,                  // 合并日志
      autorestart: true,                 // 自动重启
      max_restarts: 10,                  // 最大重启次数
      restart_delay: 1000,               // 重启延迟(毫秒)
    },
  ],
}

使用配置文件

bash
#  启动应用(默认环境)
pm2 start ecosystem.config.js

#  启动应用(生产环境)
pm2 start ecosystem.config.js --env production

#  停止应用
pm2 stop ecosystem.config.js

#  重启应用
pm2 restart ecosystem.config.js

#  删除应用
pm2 delete ecosystem.config.js

四、NestJS 项目部署

4.1 NestJS 构建配置

修改 .swcrc 配置

json
{
  "sourceMaps": false,    //  关闭 sourceMap(生产环境)
  "minify": true,         //  开启代码压缩
  "jsc": {
    "target": "es2017",
    "parser": {
      "syntax": "typescript",
      "decorators": true,
      "dynamicImport": true
    },
    "transform": {
      "decoratorMetadata": true
    }
  }
}

构建项目

bash
#  构建 NestJS 项目
npm run build

#  构建产物
# dist/
# ├── main.js             # 入口文件
# ├── app.module.js
# ├── modules/
# │   ├── course/
# │   │   ├── course.controller.js
# │   │   ├── course.service.js
# │   │   └── ...
# └── ...

4.2 NestJS 部署文件准备

code
NestJS 部署文件清单:
│
├── 必须文件
│   ├── dist/             # 构建产物
│   ├── package.json      # 依赖配置
│   ├── pnpm-lock.yaml    # 依赖锁定文件
│   ├── .env              # 环境变量
│   └── .npmrc            # npm 配置(可选)
│
├── 可选文件
│   ├── ecosystem.config.js  # PM2 配置文件
│   ├── nginx.conf           # Nginx 配置文件
│   └── README.md            # 说明文档
│
└── 不需要上传的文件
    ├── src/              # 源代码
    ├── test/             # 测试文件
    ├── node_modules/     # 依赖目录
    └── .git/             # Git 仓库

4.3 NestJS 部署步骤

步骤一:上传文件

bash
#  使用 FTP 工具上传以下文件
# - dist/
# - package.json
# - pnpm-lock.yaml
# - .env

#  或使用 SCP 命令
scp -r dist/* user@server:/home/server/project-backend-nestjs/
scp package.json user@server:/home/server/project-backend-nestjs/
scp pnpm-lock.yaml user@server:/home/server/project-backend-nestjs/
scp .env user@server:/home/server/project-backend-nestjs/

步骤二:安装依赖

bash
#  连接服务器
ssh user@server

#  进入项目目录
cd /home/server/project-backend-nestjs

#  安装依赖(使用 pnpm)
pnpm install --prod

# 或使用 npm
npm install --production

# 或使用 cnpm(国内)
cnpm install --prod

步骤三:配置环境变量

bash
#  修改 .env 文件
vi .env

#  配置数据库连接
DATABASE_URL="mysql://user:password@localhost:3306/database"

#  配置端口
PORT=3000

#  保存退出
:wq

步骤四:测试启动

bash
#  测试启动
node dist/main.js

#  检查日志
# 应该看到类似输出:
# [Nest] 12345  - INFO [NestApplication] Nest application successfully started
# 应用正在监听端口: 3000

#  停止测试
Ctrl + C

步骤五:PM2 启动

bash
#  方式一:直接启动
pm2 start dist/main.js --name nestjs-app

#  方式二:使用配置文件
# 创建 ecosystem.config.js
module.exports = {
  apps: [{
    name: 'nestjs-app',
    script: './dist/main.js',
    instances: 'max',
    exec_mode: 'cluster',
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000,
    }
  }]
}

# 启动应用
pm2 start ecosystem.config.js --env production

#  查看应用状态
pm2 list

#  查看日志
pm2 logs nestjs-app

#  查看监控
pm2 monit

4.4 NestJS 日志配置

生产环境日志配置

typescript
// src/main.ts
import { Logger } from '@nestjs/common'

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: ['error', 'warn', 'log'],  //  生产环境只记录错误、警告、日志
  })
  
  await app.listen(3000)
  Logger.log(`Application is running on: ${await app.getUrl()}`)
}
bootstrap()

日志文件管理

bash
#  NestJS 日志文件位置
logs/
├── app-info.log         # 信息日志
├── app-error.log        # 错误日志
└── app-warn.log         # 警告日志

#  查看日志
tail -f logs/app-info.log
tail -f logs/app-error.log

#  PM2 日志
pm2 logs nestjs-app

五、Nuxt.js 项目部署

5.1 Nuxt.js 构建配置

配置 package.json

json
{
  "engines": {
    "pnpm": ">=8.6.0"    //  指定 pnpm 版本
  }
}

配置 .npmrc

ini
# .npmrc
shamefully-hoist=true    #  使用扁平化依赖结构(与 npm 一致)

构建项目

bash
#  构建 Nuxt.js 项目(生产环境)
npm run build

#  构建产物
# .output/
# ├── server/            # 服务端代码
# │   ├── index.mjs      # 入口文件
# │   ├── package.json   # 服务端依赖
# │   └── ...
# └── public/            # 静态资源
#     ├── _nuxt/
#     └── ...

5.2 Nuxt.js 部署文件准备

code
Nuxt.js 部署文件清单:
│
├── 必须文件
│   ├── .output/         # 构建产物
│   ├── package.json     # 依赖配置
│   ├── pnpm-lock.yaml   # 依赖锁定文件
│   └── .npmrc           # npm 配置
│
├── 可选文件
│   ├── ecosystem.config.js  # PM2 配置文件
│   ├── nginx.conf           # Nginx 配置文件
│   └── .env.production      # 生产环境变量
│
└── 不需要上传的文件
    ├── pages/           # 页面组件
    ├── components/      # 组件
    ├── server/          # 服务端代码(源码)
    ├── node_modules/    # 依赖目录
    └── .git/            # Git 仓库

5.3 Nuxt.js 部署步骤

步骤一:上传文件

bash
#  使用 FTP 工具上传以下文件
# - .output/
# - package.json
# - pnpm-lock.yaml
# - .npmrc

#  或使用 SCP 命令
scp -r .output user@server:/home/server/project-frontend-nuxt/
scp package.json user@server:/home/server/project-frontend-nuxt/
scp pnpm-lock.yaml user@server:/home/server/project-frontend-nuxt/
scp .npmrc user@server:/home/server/project-frontend-nuxt/

步骤二:安装 pnpm

bash
#  全局安装 pnpm
npm install -g pnpm

# 或使用 cnpm 安装(国内)
cnpm install -g pnpm

#  验证安装
pnpm --version

步骤三:安装依赖

bash
#  进入项目目录
cd /home/server/project-frontend-nuxt

#  安装根目录依赖
pnpm install --prod

#  进入 .output/server 目录
cd .output/server

#  安装服务端依赖
pnpm install --prod

# 或使用国内镜像
pnpm install --prod --registry=https://registry.npmmirror.com

步骤四:测试启动

bash
#  返回根目录
cd /home/server/project-frontend-nuxt

#  测试启动(默认端口 3000)
node .output/server/index.mjs

#  测试启动(指定端口)
PORT=3010 node .output/server/index.mjs

#  检查日志
# 应该看到类似输出:
# Listening on http://[::]:3010

#  停止测试
Ctrl + C

步骤五:PM2 启动

bash
#  方式一:直接启动(指定端口)
PORT=3010 pm2 start .output/server/index.mjs --name nuxt-app

#  方式二:使用配置文件
# 创建 ecosystem.config.js
module.exports = {
  apps: [{
    name: 'nuxt-app',
    script: './.output/server/index.mjs',
    instances: 2,
    exec_mode: 'cluster',
    env_production: {
      NODE_ENV: 'production',
      PORT: 3015,
      BASE_URL: 'http://192.168.31.77:3000',
    }
  }]
}

# 启动应用
pm2 start ecosystem.config.js --env production

#  查看应用状态
pm2 list

#  查看日志
pm2 logs nuxt-app

5.4 Nuxt.js 环境变量配置

在 ecosystem.config.js 中配置

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'nuxt-app',
      script: './.output/server/index.mjs',
      instances: 2,
      exec_mode: 'cluster',
      
      //  生产环境变量
      env_production: {
        NODE_ENV: 'production',
        PORT: 3015,
        BASE_URL: 'http://192.168.31.77:3000',  // API 地址
        NUXT_PUBLIC_BASE_URL: 'http://192.168.31.77:3000',
      },
    },
  ],
}

使用环境变量

bash
#  启动应用(生产环境)
pm2 start ecosystem.config.js --env production

#  查看环境变量是否生效
pm2 show nuxt-app

六、PM2 高级配置

6.1 多应用管理

ecosystem.config.js 多应用配置

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'nestjs-app',
      script: './backend/dist/main.js',
      instances: 'max',
      exec_mode: 'cluster',
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
    },
    {
      name: 'nuxt-app',
      script: './frontend/.output/server/index.mjs',
      instances: 2,
      exec_mode: 'cluster',
      env_production: {
        NODE_ENV: 'production',
        PORT: 3015,
        BASE_URL: 'http://localhost:3000',
      },
    },
  ],
}

启动所有应用

bash
#  启动所有应用
pm2 start ecosystem.config.js --env production

#  查看所有应用
pm2 list

#  查看指定应用
pm2 show nestjs-app
pm2 show nuxt-app

#  查看所有应用日志
pm2 logs

#  查看指定应用日志
pm2 logs nestjs-app
pm2 logs nuxt-app

6.2 开机自启

bash
#  生成开机自启命令
pm2 startup

# 输出示例:
# [PM2] You have to run this command as administrator. Execute the following command:
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u username --hp /home/username

#  执行输出的命令
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u username --hp /home/username

#  保存当前应用列表
pm2 save

#  验证开机自启
systemctl status pm2-username

6.3 监控与日志

PM2 监控

bash
#  实时监控面板
pm2 monit

#  查看应用详细信息
pm2 show nuxt-app

#  查看应用描述
pm2 describe nuxt-app

PM2 日志管理

bash
#  查看所有日志
pm2 logs

#  查看指定应用日志
pm2 logs nuxt-app

#  清空日志
pm2 flush

#  重载日志
pm2 reloadLogs

#  查看日志文件位置
pm2 show nuxt-app | grep log

七、完整部署实战示例

7.1 完整部署脚本

NestJS 部署脚本

bash
#!/bin/bash

#  NestJS 部署脚本

# 配置变量
SERVER_USER="user"
SERVER_IP="192.168.31.77"
SERVER_PATH="/home/server/project-backend-nestjs"
LOCAL_PATH="./"

#  构建项目
echo "Building NestJS project..."
npm run build

#  上传文件
echo "Uploading files..."
rsync -avz --delete dist/ $SERVER_USER@$SERVER_IP:$SERVER_PATH/dist/
rsync -avz package.json $SERVER_USER@$SERVER_IP:$SERVER_PATH/
rsync -avz pnpm-lock.yaml $SERVER_USER@$SERVER_IP:$SERVER_PATH/
rsync -avz .env $SERVER_USER@$SERVER_IP:$SERVER_PATH/

#  安装依赖
echo "Installing dependencies..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
cd /home/server/project-backend-nestjs
pnpm install --prod
EOF

#  重启 PM2
echo "Restarting PM2..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
pm2 restart nestjs-app
EOF

echo "Deployment completed!"

Nuxt.js 部署脚本

bash
#!/bin/bash

#  Nuxt.js 部署脚本

# 配置变量
SERVER_USER="user"
SERVER_IP="192.168.31.77"
SERVER_PATH="/home/server/project-frontend-nuxt"
LOCAL_PATH="./"

#  构建项目
echo "Building Nuxt.js project..."
npm run build

#  上传文件
echo "Uploading files..."
rsync -avz --delete .output/ $SERVER_USER@$SERVER_IP:$SERVER_PATH/.output/
rsync -avz package.json $SERVER_USER@$SERVER_IP:$SERVER_PATH/
rsync -avz pnpm-lock.yaml $SERVER_USER@$SERVER_IP:$SERVER_PATH/
rsync -avz .npmrc $SERVER_USER@$SERVER_IP:$SERVER_PATH/

#  安装依赖
echo "Installing dependencies..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
cd /home/server/project-frontend-nuxt
pnpm install --prod
cd .output/server
pnpm install --prod
EOF

#  重启 PM2
echo "Restarting PM2..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
pm2 restart nuxt-app
EOF

echo "Deployment completed!"

7.2 完整 ecosystem.config.js

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    //  NestJS 应用
    {
      name: 'nestjs-app',
      script: './backend/dist/main.js',
      cwd: '/home/server',
      
      // 进程配置
      instances: 'max',
      exec_mode: 'cluster',
      watch: false,
      max_memory_restart: '1G',
      
      // 环境变量
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
      
      // 日志配置
      error_file: './logs/nestjs-error.log',
      out_file: './logs/nestjs-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      merge_logs: true,
    },
    
    //  Nuxt.js 应用
    {
      name: 'nuxt-app',
      script: './frontend/.output/server/index.mjs',
      cwd: '/home/server',
      
      // 进程配置
      instances: 2,
      exec_mode: 'cluster',
      watch: false,
      max_memory_restart: '1G',
      
      // 环境变量
      env_production: {
        NODE_ENV: 'production',
        PORT: 3015,
        BASE_URL: 'http://192.168.31.77:3000',
      },
      
      // 日志配置
      error_file: './logs/nuxt-error.log',
      out_file: './logs/nuxt-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      merge_logs: true,
    },
  ],
}

八、常见问题与解决方案

8.1 NVM 安装问题

问题一:无法连接 GitHub

bash
#  错误现象
curl: (7) Failed to connect to raw.githubusercontent.com

#  解决方案:使用国内镜像
curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash

问题二:NVM 命令找不到

bash
#  错误现象
nvm: command not found

#  解决方案
# 1. 使配置生效
source ~/.bashrc

# 2. 检查配置是否添加
cat ~/.bashrc | grep nvm

# 3. 手动添加配置
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

8.2 PM2 启动问题

问题一:端口被占用

bash
#  错误现象
Error: listen EADDRINUSE: address already in use :::3000

#  解决方案
# 1. 查看端口占用
lsof -i :3000

# 2. 杀死进程
kill -9 <PID>

# 3. 或使用其他端口
PORT=3001 pm2 start app.js --name my-app

问题二:模块找不到

bash
#  错误现象
Error: Cannot find module 'xxx'

#  解决方案
# 1. 重新安装依赖
pnpm install --prod

# 2. 检查 node_modules
ls node_modules | grep xxx

# 3. 清空缓存重新安装
rm -rf node_modules
pnpm install --prod

8.3 依赖安装问题

问题一:pnpm 依赖结构问题

bash
#  错误现象
Error: Cannot find module '../node_modules/xxx'

#  解决方案:使用扁平化结构
# .npmrc
shamefully-hoist=true

问题二:国内下载慢

bash
#  解决方案:使用国内镜像
# 配置 npm 镜像
npm config set registry https://registry.npmmirror.com

# 或使用 cnpm
npm install -g cnpm --registry=https://registry.npmmirror.com

# pnpm 使用镜像
pnpm install --registry=https://registry.npmmirror.com

九、最佳实践总结

9.1 SSR 部署最佳实践

code
SSR 部署最佳实践:
│
├── 1. 环境准备
│   ├── 使用 NVM 管理 Node.js 版本
│   ├── 配置默认版本
│   ├── 配置国内镜像源
│   └── 全局安装 PM2
│
├── 2. 构建优化
│   ├── 关闭 sourceMap
│   ├── 开启代码压缩
│   ├── 配置生产环境变量
│   └── 检查构建产物
│
├── 3. 文件上传
│   ├── 只上传必要文件
│   ├── 不上传 node_modules
│   ├── 不上传源代码
│   └── 验证文件完整性
│
├── 4. 依赖安装
│   ├── 使用 --prod 参数
│   ├── 配置国内镜像源
│   ├── 检查依赖安装成功
│   └── 解决依赖问题
│
├── 5. 进程管理
│   ├── 使用 PM2 配置文件
│   ├── 配置集群模式
│   ├── 配置环境变量
│   └── 配置开机自启
│
└── 6. 监控与日志
    ├── 配置日志文件
    ├── 定期清理日志
    ├── 使用 PM2 监控
    └── 配置告警通知

9.2 PM2 最佳实践

code
PM2 最佳实践:
│
├── 1. 使用配置文件
│   ├── ecosystem.config.js
│   ├── 集中管理所有配置
│   └── 版本控制配置文件
│
├── 2. 集群模式
│   ├── 生产环境使用集群模式
│   ├── instances 设置为 max 或具体数字
│   └── 充分利用多核 CPU
│
├── 3. 环境变量管理
│   ├── 使用 env_production 配置
│   ├── 不在代码中硬编码
│   └── 区分不同环境
│
├── 4. 日志管理
│   ├── 配置日志文件路径
│   ├── 配置日志格式
│   ├── 定期清理日志
│   └── 使用日志分析工具
│
└── 5. 开机自启
    ├── 使用 pm2 startup
    ├── 使用 pm2 save
    └── 验证自启配置

十、命令速查表

10.1 NVM 命令速查

命令说明
安装与配置
curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash安装 NVM(国内镜像)
source ~/.bashrc使 NVM 配置生效
nvm --version查看 NVM 版本
Node.js 管理
nvm install 18.16.0安装 Node.js 18.16.0
nvm use 18.16.0使用 Node.js 18.16.0
nvm alias default 18.16.0设置默认版本
nvm ls查看已安装版本
nvm ls-remote查看远程可用版本
nvm current查看当前使用版本

10.2 PM2 命令速查

命令说明
启动应用
pm2 start app.js --name my-app启动应用并命名
pm2 start app.js -i max集群模式启动
pm2 start ecosystem.config.js使用配置文件启动
pm2 start ecosystem.config.js --env production使用配置文件启动(生产环境)
管理应用
pm2 stop my-app停止应用
pm2 restart my-app重启应用
pm2 delete my-app删除应用
pm2 reload my-app重载应用(零停机)
查看应用
pm2 list查看所有应用
pm2 show my-app查看应用详情
pm2 monit监控面板
pm2 logs my-app查看应用日志
开机自启
pm2 startup生成开机自启命令
pm2 save保存当前应用列表

10.3 文件操作命令速查

命令说明
文件上传
rsync -avz dist/ user@server:/path/同步文件
scp -r dist/ user@server:/path/上传目录
文件查看
ls -la查看文件详情
cat ~/.bashrc查看文件内容
vi ~/.bashrc编辑文件
日志查看
pm2 logs查看 PM2 日志
tail -f logs/error.log实时查看日志
grep "error" logs/error.log搜索日志

十一、学习要点总结

11.1 核心知识点

code
SSR 项目部署核心要点:
│
├── 1. Node.js 环境安装 
│   ├── 使用 NVM 安装 Node.js
│   ├── 配置默认版本
│   ├── 配置国内镜像源
│   └── 验证安装成功
│
├── 2. PM2 进程管理 
│   ├── PM2 全局安装
│   ├── PM2 基础命令
│   ├── PM2 集群模式
│   ├── PM2 配置文件
│   └── PM2 开机自启
│
├── 3. NestJS 部署 
│   ├── 构建配置优化
│   ├── 文件上传
│   ├── 依赖安装
│   ├── 环境变量配置
│   └── PM2 启动
│
├── 4. Nuxt.js 部署 
│   ├── 构建配置优化
│   ├── pnpm 配置
│   ├── 文件上传
│   ├── 依赖安装(根目录 + .output/server)
│   └── PM2 启动
│
└── 5. 部署流程 
    ├── 构建、上传、安装、配置、启动
    └── 完整部署流程掌握

11.2 重要程度标注

知识点重要程度说明
NVM 安装与配置必须掌握,环境基础
PM2 基础使用必须掌握,进程管理核心
PM2 配置文件必须掌握,生产环境推荐
NestJS 部署必须掌握,后端部署
Nuxt.js 部署必须掌握,前端 SSR 部署
环境变量配置必须掌握,生产环境关键

11.3 学习路径规划

code
学习路径规划:
│
├── 第一阶段:理解概念(1 天)
│   ├── 理解 SSR 部署流程
│   ├── 理解 NVM 的作用
│   ├── 理解 PM2 的作用
│   └── 理解环境变量配置
│
├── 第二阶段:实践操作(2-3 天)
│   ├── 搭建服务器环境
│   ├── 部署 NestJS 项目
│   ├── 部署 Nuxt.js 项目
│   └── 配置 PM2 集群模式
│
└── 第三阶段:深入应用(持续)
    ├── CI/CD 自动化部署
    ├── Docker 容器化部署
    ├── Kubernetes 编排
    └── 高可用架构设计

十二、完整代码清单

12.1 ecosystem.config.js 完整代码

javascript
// ecosystem.config.js
module.exports = {
  apps: [
    // NestJS 应用
    {
      name: 'nestjs-app',
      script: './backend/dist/main.js',
      cwd: '/home/server',
      instances: 'max',
      exec_mode: 'cluster',
      watch: false,
      max_memory_restart: '1G',
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
      error_file: './logs/nestjs-error.log',
      out_file: './logs/nestjs-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      merge_logs: true,
    },
    
    // Nuxt.js 应用
    {
      name: 'nuxt-app',
      script: './frontend/.output/server/index.mjs',
      cwd: '/home/server',
      instances: 2,
      exec_mode: 'cluster',
      watch: false,
      max_memory_restart: '1G',
      env_production: {
        NODE_ENV: 'production',
        PORT: 3015,
        BASE_URL: 'http://192.168.31.77:3000',
      },
      error_file: './logs/nuxt-error.log',
      out_file: './logs/nuxt-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      merge_logs: true,
    },
  ],
}

12.2 .npmrc 完整代码

ini
# .npmrc
shamefully-hoist=true

12.3 部署脚本完整代码

bash
#!/bin/bash

#  完整部署脚本

# 配置变量
SERVER_USER="user"
SERVER_IP="192.168.31.77"
NESTJS_PATH="/home/server/project-backend-nestjs"
NUXT_PATH="/home/server/project-frontend-nuxt"

#  构建 NestJS
echo "Building NestJS project..."
cd backend
npm run build
cd ..

#  构建 Nuxt.js
echo "Building Nuxt.js project..."
cd frontend
npm run build
cd ..

#  上传 NestJS 文件
echo "Uploading NestJS files..."
rsync -avz --delete backend/dist/ $SERVER_USER@$SERVER_IP:$NESTJS_PATH/dist/
rsync -avz backend/package.json $SERVER_USER@$SERVER_IP:$NESTJS_PATH/
rsync -avz backend/pnpm-lock.yaml $SERVER_USER@$SERVER_IP:$NESTJS_PATH/
rsync -avz backend/.env $SERVER_USER@$SERVER_IP:$NESTJS_PATH/

#  上传 Nuxt.js 文件
echo "Uploading Nuxt.js files..."
rsync -avz --delete frontend/.output/ $SERVER_USER@$SERVER_IP:$NUXT_PATH/.output/
rsync -avz frontend/package.json $SERVER_USER@$SERVER_IP:$NUXT_PATH/
rsync -avz frontend/pnpm-lock.yaml $SERVER_USER@$SERVER_IP:$NUXT_PATH/
rsync -avz frontend/.npmrc $SERVER_USER@$SERVER_IP:$NUXT_PATH/

#  安装依赖
echo "Installing dependencies..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
# NestJS
cd /home/server/project-backend-nestjs
pnpm install --prod

# Nuxt.js
cd /home/server/project-frontend-nuxt
pnpm install --prod
cd .output/server
pnpm install --prod
EOF

#  重启 PM2
echo "Restarting PM2..."
ssh $SERVER_USER@$SERVER_IP << 'EOF'
pm2 restart all
EOF

echo "Deployment completed!"

重要提示:SSR 项目部署是全栈开发的核心技能,掌握 NVM 安装 Node.js、PM2 进程管理、NestJS 部署、Nuxt.js 部署,对实际项目部署非常重要!推荐使用 PM2 配置文件管理应用,配置集群模式提高性能!

下节预告:Nginx 反向代理与负载均衡配置,深入学习 Nginx upstream、负载均衡策略、SSL/HTTPS 配置、高可用架构设计!

笔记已按照您的格式规范整理完成,可直接用于学习复习!