构建命令
构建前确认
在运行构建命令之前,确保:
- 所有功能正常:
npm run dev下没有报错 - 类型检查通过:
npx nuxt typecheck(可选但推荐) - 环境变量就绪:确认
.env或环境变量已配置
nuxt build
构建生产版本:
npm run build
# 或
npx nuxt build什么时候用 nuxt build?
你的应用需要服务端渲染(SSR)或包含 API 路由时使用。构建产物包含服务端代码和客户端代码,需要 Node.js 环境运行。
构建产物详解
输出到 .output/ 目录:
.output/
├── public/ # 客户端资源
│ ├── _nuxt/ # JS、CSS、图片(文件名含哈希,可永久缓存)
│ │ ├── entry.xxx.js
│ │ ├── page-about.xxx.js
│ │ └── ...
│ └── __payload.json # SSR Payload(可选)
├── server/ # 服务端代码
│ ├── index.mjs # 服务入口文件
│ ├── chunks/ # 服务端代码分块
│ └── package.json # 服务端依赖声明
└── nitro.json # Nitro 部署配置每个目录的作用
| 目录 | 内容 | 部署时需要? |
|---|---|---|
public/ | 浏览器下载的所有文件 | ✅ 需要,作为静态资源 |
server/ | Node.js 服务端代码 | ✅ 需要(SSR 模式) |
nitro.json | 部署配置信息 | ✅ 需要 |
INFO
️ .output/ 目录不应提交到 Git 它是构建产物,每次 nuxt build 都会重新生成。将其加入 .gitignore
常用选项
# 指定预设
NUXT_NITRO_PRESET=vercel npx nuxt build
# 构建分析(v4.4+)
npx nuxt build --profile
# 详细分析
npx nuxt build --profile=verbose构建分析(v4.4+)
为什么需要构建分析?
当构建速度慢或产物体积过大时,分析报告帮你定位瓶颈。
生成三种性能报告:
.nuxt/
├── perf-trace.json # Chrome Trace 格式
├── perf-report.json # JSON 报告
└── nuxt-build.cpuprofile # CPU Profile- Chrome Trace:在
chrome://tracing中打开,查看每个构建步骤的耗时 - CPU Profile:在 Chrome DevTools → Performance 中打开,查看 CPU 热点
nuxt preview
构建后在本地预览生产版本:
npm run preview
# 或
npx nuxt previewnuxt preview 做了什么?
- 启动一个本地服务器运行
.output/中的构建产物 - 模拟生产环境运行(代码压缩、优化后的版本)
- 默认在
http://localhost:3000启动
为什么构建后要预览?
| 问题 | 只在 dev 模式测试 | 在 preview 模式测试 |
|---|---|---|
| 代码压缩导致的 bug | ❌ 发现不了(dev 模式不压缩) | ✅ 能发现 |
| CSS/JS 体积问题 | ❌ 看不出(没有打包) | ✅ 可以分析 |
| SSR 数据传递问题 | ❌ 可能遗漏 | ✅ 更接近生产 |
| 路由规则不生效 | ❌ dev 模式行为不同 | ✅ 能验证 |
最佳实践
每次构建后用 nuxt preview 快速验证,确保生产版本没有明显问题,再进行部署。
preview 常见问题
# 端口被占用
npx nuxt preview --port 3001
# 预览 SSG 站点
npx nuxt preview # 先 nuxt generate,再 previewnuxt generate
生成静态站点(SSG):
npm run generate
# 或
npx nuxt generate什么时候用 nuxt generate?
你的应用是纯内容站点(博客、文档、落地页),不需要服务端渲染和 API 路由时使用。产物是纯 HTML/CSS/JS 文件,可以部署到任何静态托管平台。
预渲染所有页面为 HTML 文件:
.output/
└── public/
├── index.html
├── about/
│ └── index.html
├── blog/
│ ├── first-post/
│ │ └── index.html
│ └── index.html
├── _payload.json
└── _nuxt/ # JS、CSS、图片nuxt generate 的工作过程
- 先执行
nuxt build - 然后对每个路由执行一次 SSR,生成 HTML 文件
- 最终产物只有
public/目录,不需要 Node.js 服务器
INFO
️ nuxt generate 的限制:
- 它会尝试预渲染所有页面
- 如果页面依赖运行时数据(如用户登录状态),预渲染可能失败
- 动态路由(如
[id].vue)需要在nitro.prerender.routes中手动列出,或配置crawlLinks - 页面数量很多时(如几千篇文章),构建会非常慢
替代方案
如果页面太多或有动态内容,用 nuxt build + ISR/SWR 缓存策略,只预渲染关键页面。
与 nuxt build 的区别
| 命令 | 输出 | 需要服务器 | 适用场景 | 部署成本 |
|---|---|---|---|---|
nuxt build | 服务端 + 客户端 | ✅ 需要 | SSR 应用、有 API 路由 | 需要服务器(VPS/云) |
nuxt generate | 纯静态文件 | ❌ 不需要 | 静态站点、纯内容展示 | 免费(GitHub Pages 等) |
简单判断
如果你的项目有 server/api/ 目录或需要 SSR → 用 nuxt build。如果是纯展示站点 → 用 nuxt generate。
动态路由的预渲染
nuxt generate 不会自动发现动态路由(如 [id].vue),需要手动指定:
export default defineNuxtConfig({
nitro: {
prerender: {
routes: [
'/blog/post-1',
'/blog/post-2',
'/blog/post-3',
// 或者用 crawlLinks 自动发现页面中的链接
],
crawlLinks: true, // 自动爬取页面中的链接
},
},
})crawlLinks 做了什么?
渲染每个页面后,扫描页面中的 <a> 标签,发现新路由就继续渲染。这样就不需要手动列出所有路由。但如果某些页面没有链接指向(如只有通过搜索才能访问),它们不会被预渲染。
完整的构建-预览-部署流程
开发阶段 验证阶段 部署阶段
──────── ──────── ────────
npm run dev → nuxt build → nuxt preview → 部署到服务器
(开发调试) (构建生产版本) (本地验证) (上线)# 1. 开发
npm run dev
# 2. 类型检查(可选但推荐)
npx nuxt typecheck
# 3. 构建
npm run build
# 4. 本地预览验证
npm run preview
# 5. 确认无误后部署
# (取决于部署平台,详见 03-部署平台)Nitro 预设
通过预设控制部署目标,Nitro 会为不同平台生成适配的代码:
export default defineNuxtConfig({
nitro: {
preset: 'node-server', // 预设名称
},
})| 预设 | 说明 | 适用场景 | 构建产物特点 |
|---|---|---|---|
node-server | Node.js 服务器(默认) | 自建服务器、VPS | 独立 Node.js 进程 |
node-cluster | Node.js 集群 | 多核服务器、高并发 | 自动利用所有 CPU 核心 |
vercel | Vercel | 快速部署、免费起步 | Vercel Serverless Functions |
netlify | Netlify | 静态站点 + 轻量 SSR | Netlify Functions |
cloudflare-pages | Cloudflare Pages | 边缘计算、全球加速 | Workers 运行时 |
deno-deploy | Deno Deploy | Deno 运行时 | Deno 运行时 |
bun | Bun 运行时 | 高性能 Node 替代 | Bun 运行时 |
static | 纯静态 | GitHub Pages、S3 托管 | 纯静态文件 |
TIP
也可以通过环境变量指定预设:NITRO_PRESET=vercel nuxt build 适合 CI/CD 环境中动态切换
预设如何影响构建?
不同预设会生成不同的服务入口文件(server/index.mjs),但你的业务代码(server/api/、server/middleware/ 等)不变。这就是 Nitro "一次构建,处处部署"的核心。
构建优化
1. 拆分 vendor 包
export default defineNuxtConfig({
vite: {
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor': ['vue', 'vue-router'], // 不常变化的库单独打包
},
},
},
},
},
})为什么拆分 vendor?
vue、vue-router等库很少变化- 单独打包后,浏览器可以长期缓存这些文件
- 你的业务代码变化时,用户只需重新下载业务代码的 chunk
- 而不是整个 bundle 都重新下载
2. 路由规则缓存
export default defineNuxtConfig({
routeRules: {
'/': { swr: 3600 }, // 首页缓存 1 小时
'/blog/**': { isr: 60 }, // 博客每分钟重新生成
},
})缓存策略选择
- SWR(Stale-While-Revalidate):先返回旧缓存,后台刷新。用户始终能立即看到内容,但可能看到稍旧的数据
- ISR(Incremental Static Regeneration):缓存过期后重新生成。数据更准确,但过期后用户可能短暂等待
- prerender:构建时生成。最简单,但数据不更新
3. Payload 优化
export default defineNuxtConfig({
experimental: {
payloadExtraction: 'client',
},
})payloadExtraction 的三个值
| 值 | 行为 | 适用场景 |
|---|---|---|
false(默认) | Payload 内联在 HTML 中 | 小型应用,Payload 不大 |
'client' | Payload 内联 + 生成独立文件 + LRU 缓存 | 中大型应用(推荐) |
'server' | 仅在服务端提取 | 特殊场景 |
'client' 模式的好处
- 首次访问:Payload 内联在 HTML 中(快速渲染)
- 客户端导航:从独立文件加载 Payload(可被浏览器缓存)
- LRU 缓存:服务端缓存已渲染的 Payload(减少重复计算)
4. 按需加载
<!-- 懒加载大组件 -->
<LazyHeavyComponent v-if="showHeavy" />
<!-- 懒加载图片 -->
<NuxtImg loading="lazy" />常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 构建内存溢出(OOM) | 项目过大 | 设置 NODE_OPTIONS=--max-old-space-size=4096 |
nuxt generate 动态路由未生成 | 未配置预渲染路由 | 在 nitro.prerender.routes 中列出,或开启 crawlLinks |
| 构建产物过大 | 依赖未 Tree-shake | 使用 nuxt build --profile 分析,移除无用依赖 |
.output/ 被提交到 Git | 忘记加入 .gitignore | 将 .output 和 *.output 加入 .gitignore |
| 预设选择错误导致部署失败 | 预设与部署平台不匹配 | 确认预设与实际部署平台一致 |
| preview 报错 "No build found" | 未先构建 | 先运行 nuxt build 或 nuxt generate |
| 构建慢 | 文件监听或类型生成 | 增加内存、用 --profile 分析瓶颈 |
知识脉络
模块系统 → 你在这里:构建命令
│
├─→ 下一步:预览(本地验证构建结果)
│
├─→ 下一步:部署平台(选择部署方案)
│
└─→ 相关:环境变量(构建时注入配置)