225 lines
6.4 KiB
Markdown
225 lines
6.4 KiB
Markdown
# Next.js Standalone 模式详解
|
||
|
||
## 📖 什么是 Standalone 模式?
|
||
|
||
**Standalone 模式**是 Next.js 提供的一种**独立部署模式**,它会将应用及其所有运行时依赖打包成一个**自包含的独立目录**,可以直接在服务器上运行,**无需安装完整的项目依赖**。
|
||
|
||
## 🔧 如何启用?
|
||
|
||
在 `next.config.mjs` 中配置:
|
||
|
||
```javascript
|
||
const nextConfig = {
|
||
output: 'standalone', // 启用 standalone 模式
|
||
// ... 其他配置
|
||
}
|
||
```
|
||
|
||
你的项目已经启用:
|
||
|
||
```9:9:next.config.mjs
|
||
output: 'standalone',
|
||
```
|
||
|
||
## 📦 构建产物结构
|
||
|
||
### 普通模式(非 standalone)
|
||
|
||
```
|
||
项目根目录/
|
||
├── .next/ # 构建输出
|
||
│ ├── static/ # 静态资源
|
||
│ └── server/ # 服务端代码(不完整)
|
||
├── node_modules/ # 需要完整安装所有依赖
|
||
├── package.json
|
||
└── public/ # 静态文件
|
||
```
|
||
|
||
**部署时需要**:
|
||
- 上传整个项目
|
||
- 在服务器上运行 `npm install` 安装所有依赖
|
||
- 使用 `npm start` 或 `next start` 启动
|
||
|
||
### Standalone 模式
|
||
|
||
```
|
||
.next/
|
||
└── standalone/ # 独立部署目录(包含所有运行时依赖)
|
||
├── server.js # 主启动文件 ⭐
|
||
├── package.json # 精简的依赖列表
|
||
├── node_modules/ # 只包含运行时必需的依赖(已优化)
|
||
│ └── next/ # Next.js 核心
|
||
└── ... # 其他运行时文件
|
||
```
|
||
|
||
**部署时只需要**:
|
||
- 上传 `.next/standalone` 目录
|
||
- 复制 `.next/static` 静态资源
|
||
- 复制 `public` 目录
|
||
- 使用 `node server.js` 启动(**不需要 npm/next 命令**)
|
||
|
||
## 🚀 启动方式对比
|
||
|
||
### 普通模式
|
||
|
||
```bash
|
||
# 需要先安装依赖
|
||
npm install --production
|
||
|
||
# 使用 next 命令启动
|
||
npm start
|
||
# 或
|
||
next start -p 30006
|
||
```
|
||
|
||
### Standalone 模式
|
||
|
||
```bash
|
||
# 不需要安装依赖,直接启动
|
||
node server.js
|
||
|
||
# 或指定端口
|
||
PORT=30006 node server.js
|
||
|
||
# 使用 PM2
|
||
pm2 start server.js --name soul
|
||
```
|
||
|
||
你的项目 PM2 配置:
|
||
|
||
```10:10:ecosystem.config.cjs
|
||
script: 'server.js',
|
||
```
|
||
|
||
## ✨ Standalone 模式的优势
|
||
|
||
### 1. **部署包更小** 📉
|
||
- 只包含运行时必需的依赖
|
||
- 不包含开发依赖(如 TypeScript、ESLint 等)
|
||
- 通常比完整 `node_modules` 小 50-70%
|
||
|
||
### 2. **启动更快** ⚡
|
||
- 无需在服务器上运行 `npm install`
|
||
- 直接运行 `node server.js` 即可
|
||
- 减少部署时间
|
||
|
||
### 3. **环境独立** 🔒
|
||
- 不依赖服务器上的 Node.js 版本(只要兼容)
|
||
- 不依赖全局安装的 npm 包
|
||
- 减少环境配置问题
|
||
|
||
### 4. **适合单机/宝塔部署**
|
||
- 产出目录小,无需完整 node_modules
|
||
- 构建和运行环境分离
|
||
- 本项目使用 standalone 配合宝塔 + `scripts/devlop.py` 部署(见 `Next.js宝塔部署方案.md`)。
|
||
|
||
### 5. **安全性更好** 🛡️
|
||
- 不暴露开发依赖
|
||
- 减少攻击面
|
||
- 生产环境更干净
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. **启动方式不同**
|
||
|
||
❌ **错误**:
|
||
```bash
|
||
npm start # standalone 模式下没有 next 命令
|
||
next start # 命令不存在
|
||
```
|
||
|
||
✅ **正确**:
|
||
```bash
|
||
node server.js # 直接运行 Node.js
|
||
```
|
||
|
||
### 2. **需要手动复制静态资源**
|
||
|
||
Standalone 输出**不包含**:
|
||
- `.next/static` - 静态资源(CSS、JS 等)
|
||
- `public` - 公共静态文件
|
||
|
||
**部署时需要手动复制**:
|
||
|
||
```bash
|
||
# 复制静态资源
|
||
cp -r .next/static /www/wwwroot/soul/.next/
|
||
cp -r public /www/wwwroot/soul/
|
||
```
|
||
|
||
你的部署脚本已经处理了:
|
||
|
||
```407:424:scripts/deploy_soul.py
|
||
# 复制 .next/static
|
||
static_dst = os.path.join(staging, ".next", "static")
|
||
if os.path.exists(static_dst):
|
||
shutil.rmtree(static_dst)
|
||
os.makedirs(os.path.dirname(static_dst), exist_ok=True)
|
||
shutil.copytree(static_src, static_dst)
|
||
|
||
# 复制 public
|
||
if os.path.isdir(public_src):
|
||
public_dst = os.path.join(staging, "public")
|
||
if os.path.exists(public_dst):
|
||
shutil.rmtree(public_dst)
|
||
shutil.copytree(public_src, public_dst)
|
||
|
||
# 复制 ecosystem.config.cjs
|
||
if os.path.isfile(ecosystem_src):
|
||
shutil.copy2(ecosystem_src, os.path.join(staging, "ecosystem.config.cjs"))
|
||
```
|
||
|
||
### 3. **Windows 构建问题**
|
||
|
||
Windows 上构建 standalone 可能遇到符号链接权限问题:
|
||
|
||
```
|
||
EPERM: operation not permitted, symlink
|
||
```
|
||
|
||
**解决方案**(你的文档已说明):
|
||
|
||
```181:196:DEPLOYMENT.md
|
||
### Windows 本地执行 `pnpm build` 报 EPERM symlink
|
||
|
||
本项目使用 `output: 'standalone'`,构建时 Next.js 会创建符号链接。**Windows 默认不允许普通用户创建符号链接**,会报错:
|
||
|
||
- `EPERM: operation not permitted, symlink ... -> .next\standalone\node_modules\...`
|
||
|
||
**可选做法(任选其一):**
|
||
|
||
1. **开启 Windows 开发者模式(推荐,一劳永逸)**
|
||
- 设置 → 隐私和安全性 → 针对开发人员 → **开发人员模式** 打开
|
||
- 开启后无需管理员即可创建符号链接,本地 `pnpm build` 可正常完成。
|
||
|
||
2. **以管理员身份运行终端再执行构建**
|
||
- 右键 Cursor/终端 → "以管理员身份运行",在项目根目录执行 `pnpm build`。
|
||
|
||
若只做部署、不在本机打 standalone 包,可用 `python scripts/devlop.py --no-build` 跳过构建后上传已有包,或由服务器/计划任务在服务器上执行构建。
|
||
```
|
||
|
||
## 📊 对比总结
|
||
|
||
| 特性 | 普通模式 | Standalone 模式 |
|
||
|------|---------|----------------|
|
||
| **部署包大小** | 大(完整 node_modules) | 小(仅运行时依赖) |
|
||
| **服务器安装** | 需要 `npm install` | 不需要 |
|
||
| **启动命令** | `npm start` / `next start` | `node server.js` |
|
||
| **部署时间** | 较慢(需安装依赖) | 较快(直接运行) |
|
||
| **环境要求** | 需要 npm/next 命令 | 只需要 Node.js |
|
||
| **适用场景** | 传统部署 | 容器化、独立部署 |
|
||
|
||
## 🎯 你的项目使用 Standalone 的原因
|
||
|
||
1. **宝塔服务器部署**:减少服务器上的依赖安装
|
||
2. **单机/宝塔部署**:目录小,启动快
|
||
3. **GitHub Actions 部署**:构建和运行环境分离
|
||
4. **团队协作**:减少环境配置问题
|
||
|
||
## 📚 相关文档
|
||
|
||
- [Next.js Standalone 官方文档](https://nextjs.org/docs/pages/api-reference/next-config-js/output#standalone)
|
||
- 你的项目部署文档:`DEPLOYMENT.md`
|
||
- PM2 配置:`ecosystem.config.cjs`
|
||
- 部署脚本:`scripts/deploy_soul.py`
|