模块五:部署与生产 | 前置要求:第 18 课 覆盖文档:Deploying、Static Exports、Single-Page Applications 时长:90 分钟
一、Node.js 部署
1.1 标准流程
# 1. 构建生产产物
next build
# 2. 启动生产服务器
next start -p 3000
构建产物在 .next/ 目录,next start 启动一个 Node.js HTTP 服务器,支持所有 Next.js 功能:SSR、ISR、Middleware、Streaming 等。
1.2 构建产物结构
.next/
├── server/ # 服务端渲染代码
├── static/ # 客户端静态资源
├── cache/ # ISR/缓存数据
├── BUILD_ID # 构建标识
└── routes-manifest.json
二、Docker 部署
2.1 output: 'standalone' 模式
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
output: 'standalone',
}
export default nextConfig
standalone 模式自动追踪依赖,生成最小化独立运行目录,无需安装 node_modules。
2.2 多阶段 Dockerfile
# 阶段 1:安装依赖
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
# 阶段 2:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 阶段 3:生产镜像(最小化)
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# 复制 standalone 产物
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
2.3 镜像对比
| 方案 | 镜像大小 | 说明 |
|---|---|---|
| 完整 node_modules | ~1GB+ | 包含所有依赖 |
| standalone | ~100-200MB | 仅必要文件 |
| standalone + alpine | ~80-150MB | 最小基础镜像 |
三、静态导出
3.1 配置
// next.config.ts
const nextConfig: NextConfig = {
output: 'export',
}
next build 生成纯静态 HTML/CSS/JS 到 out/ 目录,可部署到任何静态托管服务。
3.2 支持与不支持的功能
| 支持 | 不支持 |
|---|---|
| Server Components(静态渲染) | 动态路由(无 generateStaticParams) |
| Client Components | Route Handlers(依赖请求的) |
| Image Optimization(自定义 loader) | Middleware |
| CSS/Sass/Tailwind | ISR / 增量静态再生 |
| generateStaticParams | cookies() / headers() |
3.3 图片优化适配
const nextConfig: NextConfig = {
output: 'export',
images: {
loader: 'custom',
loaderFile: './image-loader.ts',
},
}
// image-loader.ts
export default function cloudinaryLoader({
src, width, quality,
}: { src: string; width: number; quality?: number }) {
return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality || 75}/${src}`
}
四、SPA 模式
静态导出 + 客户端路由 = 单页应用:
// app/layout.tsx
export const dynamic = 'force-static'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
)
}
所有页面预渲染为静态 HTML,客户端接管路由导航。
五、GitHub Pages 部署
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci && npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./out
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
steps:
- uses: actions/deploy-pages@v4
注意 basePath 配置:
const nextConfig: NextConfig = {
output: 'export',
basePath: '/repo-name', // GitHub Pages 子路径
}
六、Adapters 概览
| 适配器 | 状态 | 说明 |
|---|---|---|
| Vercel | 已验证 | 原生支持所有功能 |
| Bun | 已验证 | 兼容 Node.js API |
| Netlify | 社区 | 通过 @netlify/next 适配 |
| AWS Lambda | 社区 | 需 serverless 框架 |
| Cloudflare | 社区 | Edge Runtime 限制 |
6.1 平台功能矩阵
| 功能 | Node.js | Docker | 静态导出 | Vercel |
|---|---|---|---|---|
| SSR | 完整 | 完整 | 不支持 | 完整 |
| ISR | 完整 | 完整 | 不支持 | 原生 |
| Middleware | 完整 | 完整 | 不支持 | Edge |
| Image Optimization | 完整 | 完整 | 自定义 loader | 原生 |
| Streaming | 完整 | 完整 | 不支持 | 原生 |
| PPR | 完整 | 完整 | 不支持 | 原生 |
七、课后练习
练习 1:Node.js 部署(基础)
在本地运行 next build + next start,检查 .next/ 目录结构。
练习 2:Docker 化(中阶)
编写多阶段 Dockerfile,使用 output: 'standalone',对比镜像大小。
练习 3:静态导出(高阶)
将一个动态路由项目改为 output: 'export',处理所有不兼容功能。
练习 4:平台评估(资深)
评估你的目标部署平台,列出功能支持矩阵和性能保真度差异。
八、关键要点总结
- Node.js 部署:
next build+next start,支持所有功能 - Docker:
output: 'standalone'+ 多阶段构建,镜像缩小 80%+ - 静态导出:
output: 'export',纯静态但功能受限 - SPA 模式:静态导出 + 客户端路由
- Adapters:Vercel/Bun 已验证,其他平台通过社区适配器
- 选择依据:功能需求 → 基础设施条件 → 性能保真度
下一课:第 32 课:部署(下)