Skip to content
运行时配置:
Nuxt.js 渲染模式与部署
概述
Nuxt 把渲染决策从应用级转向路由级:全局 ssr: false 让整个应用退化为 SPA,ssr: true 则沿用传统 SSR,而 routeRules 允许在同一个项目里让 /blog 静态生成、/admin 服务端渲染、/dashboard 纯客户端渲染。这套能力由 Nitro 引擎支撑,构建时根据规则决定最终产物是 Node 服务、Serverless 函数还是纯静态文件。
渲染策略
SSR(服务端渲染)
每个请求由 Nitro 服务器处理,Vue 组件在服务端渲染成 HTML 返回浏览器,同时嵌入一份序列化数据用于客户端 hydration。适合需要 SEO 和首屏速度、且内容与请求上下文强相关的页面,例如用户中心、商品详情。
默认配置就是 SSR 模式,无需额外修改:
ts
export default defineNuxtConfig({
// ssr 默认为 true
})也可以通过环境变量在运行时覆写,比如 NUXT_SSR=false 可以临时降级,不过这种用法并不常见。
SSG(静态站点生成)
构建时将路由预渲染为 HTML 文件,无需 Node.js 运行时,所有请求由静态文件直接响应。适合内容固定、更新频率低的页面,如文档、营销站、博客。
执行 nuxi generate 就会走这条路。构建完成后 .output/public 目录中就是完整的静态站点。
SPA(单页应用)
ssr: false 关闭服务端渲染后,服务端只返回一个空壳 index.html,所有内容由客户端 JavaScript 动态生成。这种方式对 SEO 不友好,但部署简单——任何静态文件服务器都能运行。登录后应用、内部后台等不需要搜索引擎索引的页面,自然会倾向 SPA。
ts
export default defineNuxtConfig({
ssr: false
})混合渲染
通过 routeRules 为不同路由指定渲染策略,无需在 SSR、SSG、SPA 之间做全局取舍:
ts
export default defineNuxtConfig({
routeRules: {
'/admin/**': { ssr: false }, // 仪表盘纯客户端
'/blog/**': { prerender: true }, // 博客静态生成
'/api/**': { cors: true } // API 路由保持 SSR,顺带开启 CORS
}
})prerender 规则依赖 Nitro 预渲染,在 nuxi generate 或 nuxi build --prerender 时生效。ssr: false 规则不管哪种构建方式,都会让对应路由走客户端渲染。
需要留意作用的边界:只有 prerender 规则可以在纯静态托管上完整工作,ssr、swr 等依赖服务端运行时的规则,必须部署到能运行 Nitro 服务器的平台。
配置渲染与构建行为
ssr 开关
nuxt.config.ts 中的 ssr 控制整个应用的服务端渲染是否启用。若设为 false,整个应用退化为 SPA,即便在 routeRules 中为个别路由指定 ssr: true 也不会生效。混合渲染的正确方式是保持全局 ssr: true,再通过 routeRules 关闭特定路由的 SSR。
nitro 选项
Nitro 是 Nuxt 的服务端引擎,它的配置决定构建产物的结构以及适配的目标平台。核心字段是 preset 和 output。
ts
export default defineNuxtConfig({
nitro: {
preset: 'node-server',
output: {
dir: '.output'
}
}
})preset 告诉 Nitro 生成哪种运行环境的入口文件。默认 node-server 产出一个普通的 Node.js 服务,其他值如 vercel、netlify、cloudflare_pages 会输出对应平台的 Serverless 函数或边缘计算格式。
output.dir 改变构建产物顶级目录,默认 .output,一般无需改动。
Nitro 的产物与运行机制
nuxi build 结束后,.output 目录大致如下:
.output
├── public/ # 静态资源:_nuxt、favicon 等
└── server/
└── index.mjs # Node.js 服务器入口(preset 为 node-server 或类似时)public 可以直接放到任意静态文件服务器上。server/index.mjs 是平台无关的 Nitro 服务器实例,封装了路由处理、静态文件服务、API 路由等逻辑,启动时监听环境变量 PORT(默认 3000)。
如果 preset 是 vercel,产物中不会出现 server/index.mjs,而是生成 .vercel/output 目录,其中包含 Vercel Serverless Functions 需要的签名文件和静态资源。
nuxi build 与 nuxi generate
nuxi build
生产构建命令,默认不执行预渲染。生成 .output,包含 Nitro 服务器和静态文件。部署时需要能运行 Node.js 的环境。
bash
npx nuxi build带上 --prerender 标志时,Nitro 会在构建结束后对所有标记为 prerender 的路由执行预渲染,效果等同于 nuxi generate。不过产物依然是 .output,服务器仍然可以处理动态请求。这种模式适合需要混合渲染且部署到 Node 或 Serverless 平台的场景。
nuxi generate
专门面向全静态生成。内部会先执行构建流程,然后对所有可发现的静态路由预渲染,并把 HTML 放入 .output/public。
bash
npx nuxi generate动态路由(例如 /posts/[id])无法被自动扫描,这些路由不会默认预渲染,需要在配置里显式声明:
ts
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/posts/1', '/posts/2']
}
}
})或者结合 routeRules 与爬虫:
ts
export default defineNuxtConfig({
routeRules: {
'/posts/**': { prerender: true }
},
nitro: {
prerender: {
crawlLinks: true,
routes: ['/'] // 从首页开始抓取链接
}
}
})当 crawlLinks 为 true 时,预渲染阶段会像爬虫一样从 routes 指定的入口出发,提取 <a> 链接并递归预渲染。适合内容通过链接串联的站点,比如博客。
旧的 generate.routes 配置在 Nuxt 3 中已经失效,沿用会导致对应路由被跳过且不报错,排查起来很麻烦。
部署到 Node.js 服务端
默认 preset node-server 产出的服务直接用 Node.js 启动:
bash
node .output/server/index.mjs启动时检查 PORT 环境变量,未设置则使用 3000。一般会在前面放一层反向代理(如 Nginx、Caddy)处理 HTTPS 和静态文件缓存,只需保证代理转发到 Nuxt 监听的端口。
需要将整个 .output 目录上传到服务器。如果项目依赖了原生模块(比如 @nuxt/image 的 sharp),要确保部署环境的 Node 版本与构建环境一致,或者使用预编译好的二进制包。
全站静态生成与预渲染
nuxi generate 生成纯静态站点后,只需要 .output/public 目录。每个路由对应一个包含 index.html 的目录,例如:
.output/public
├── index.html
├── blog/
│ └── index.html
├── posts/
│ ├── 1/
│ │ └── index.html
│ └── 2/
│ └── index.html
└── ...静态文件服务器需要配置 fallback 到 index.html,以支持 SPA 模式下的客户端路由回退。对于已经预渲染的页面,每个路由的 HTML 文件存在,不会触发 fallback;只有未预渲染的路由(例如管理后台的客户端动态路由)才需要 fallback。
routeRules 中设置了 ssr: false 的路由部署到纯静态托管时,这些页面不会真的被预渲染,而是共用同一个 index.html 外壳,由客户端 Vue Router 接管。托管平台如果没有正确配置 fallback,刷新页面时就会出现 404。
Nitro 预设与自动部署
预设(preset)是 Nitro 最实用的能力之一。修改 nitro.preset 后重新构建,产物结构自动适配目标平台,无需改动应用代码。
Vercel
ts
export default defineNuxtConfig({
nitro: {
preset: 'vercel'
}
})构建输出 .vercel/output,可直接被 Vercel 识别。Vercel 将服务端入口编译为 Serverless Functions,静态资源由 Vercel Edge Cache 缓存。动态路由的 ISR 行为由 routeRules 中的 swr 配置控制,预设本身不决定缓存策略。
Netlify
ts
export default defineNuxtConfig({
nitro: {
preset: 'netlify'
}
})同样产出 Netlify 要求的目录结构。Netlify Functions 运行 SSR 请求,静态文件与重定向规则自动生成。可以通过直接推送仓库部署,也可手动上传构建产物。
Cloudflare Pages
ts
export default defineNuxtConfig({
nitro: {
preset: 'cloudflare_pages'
}
})构建产物符合 Cloudflare Pages 目录规范,结合 Git 集成或 Wrangler CLI 上传后运行在边缘函数环境中。需要注意边缘函数有尺寸和执行时间限制,以及 Node.js API 不完整,一些依赖可能无法直接运行。
平台预设也可以在对应平台构建时自动检测,不必显式配置,但显式指定能避免检测环节的不确定性。
运行时配置:runtimeConfig 与环境变量
runtimeConfig 用于注入在构建时未确定、运行时才需要提供的应用参数。字段分为两类:public 中的会暴露到客户端,其余只存在于服务端。
ts
export default defineNuxtConfig({
runtimeConfig: {
// 仅服务端可用
apiToken: '',
// 公共,服务端和客户端都能读取
public: {
siteUrl: 'https://example.com',
analyticsId: ''
}
}
})服务端通过 useRuntimeConfig().apiToken 取值,客户端通过 useRuntimeConfig().public.siteUrl。部署时可以用环境变量覆盖这些默认值,Nuxt 自动做映射——NUXT_API_TOKEN 对应 apiToken,NUXT_PUBLIC_SITE_URL 覆盖 public.siteUrl。
runtimeConfig 的值在构建时通过环境变量嵌入服务端 bundle,而不是在服务器启动时动态读取。这意味着如果只在运行环境中修改环境变量而不重新构建,服务端读取到的依然是旧值。对于 Docker 镜像构建和 CI/CD 管线,需要保证构建阶段与运行阶段的环境变量一致。
混合渲染与按需静态生成
routeRules 里的 prerender 规则让指定路由在构建时变成静态 HTML。如果页面内容会变,又不想每次都走 SSR,可以用 swr 规则。
ts
export default defineNuxtConfig({
routeRules: {
'/products/**': {
swr: 3600 // 第一次请求后缓存 1 小时,期间直接返回缓存内容,过期后后台重新生成
}
}
})swr 只能在有服务端运行时的平台使用(Node、Vercel、Netlify 等)。它结合了静态生成和动态渲染:首次请求时 SSR 生成页面并缓存,后续请求直接返回缓存,达到接近静态文件的速度;缓存失效后的下一个请求触发一次后台重新渲染。
部署到纯静态托管时,swr 不会起任何作用——那些路由会退化为普通的 SSR 请求,但环境又不支持,会导致运行时错误。
注意点与限制
routeRules中依赖服务端运行的规则(ssr、swr、isr等)在纯静态托管上无效,只有prerender和redirect能正常工作。- 动态路由的预渲染必须显式声明路由路径或通过
crawlLinks抓取,无法依赖自动发现。 runtimeConfig的值在构建时固化,更新环境变量需要重新构建。- 不同 Nitro preset 生成的目录结构差异较大,自动化部署脚本不能假设固定路径。
- Cloudflare Pages 等边缘平台对 Node.js 核心 API 支持有限,使用
node:模块的代码可能运行失败。 - 混合渲染虽然灵活,但策略复杂度上升,排查运行行为时需要同时理解构建期和运行时两条路径。
参考链接
- [1] https://nuxt.com/docs/getting-started/rendering
- [2] https://nuxt.com/docs/guide/concepts/rendering#server-side-rendering
- [3] https://nuxt.com/docs/guide/concepts/rendering#static-site-generation
- [4] https://nuxt.com/docs/guide/concepts/rendering#single-page-applications
- [5] https://nuxt.com/docs/guide/concepts/rendering#route-rules
- [6] https://nuxt.com/docs/api/nuxt-config#nitro
- [7] https://nuxt.com/docs/guide/concepts/server-engine
- [8] https://nuxt.com/docs/api/commands/build
- [9] https://nuxt.com/docs/api/commands/generate
- [10] https://nuxt.com/docs/getting-started/deployment#the-output-directory
- [11] https://nuxt.com/docs/getting-started/deployment#node-server
- [12] https://nuxt.com/docs/getting-started/deployment#static-hosting
- [13] https://nuxt.com/docs/deploy/vercel
- [14] https://nuxt.com/docs/deploy/netlify
- [15] https://nuxt.com/docs/deploy/cloudflare
- [16] https://nuxt.com/docs/guide/going-further/runtime-config
- [19] https://github.com/unjs/nitro
