渲染模式✅
本主题涵盖 Nuxt 的多种渲染模式,包括 SSR、SSG、SPA 和混合渲染的特点、使用场景和配置方式。
Nuxt 支持哪些渲染模式,各有什么特点?
答案
核心概念
Nuxt 支持多种渲染模式,每种模式都有其特定的使用场景和优势,开发者可以根据项目需求选择合适的渲染策略。
主要渲染模式
| 渲染模式 | 全称 | 特点 | 适用场景 |
|---|---|---|---|
| SSR | Server-Side Rendering | 服务端渲染,每次请求生成 HTML | 动态内容、SEO 重要 |
| SSG | Static Site Generation | 静态站点生成,构建时预渲染 | 静态内容、高性能 |
| SPA | Single Page Application | 单页应用,客户端渲染 | 交互性强、用户个性化 |
| 混合渲染 | Hybrid Rendering | 不同页面使用不同渲染模式 | 复杂应用、灵活需求 |
详细对比
-
SSR (服务端渲染)
// nuxt.config.tsexport default defineNuxtConfig({ssr: true // 默认值})- 优势:SEO 友好、首屏加载快、动态内容支持
- 劣势:服务器负载高、缓存复杂
- 适用:电商网站、新闻网站、博客
-
SSG (静态站点生成)
// nuxt.config.tsexport default defineNuxtConfig({nitro: {prerender: {routes: ['/'] // 预渲染路由}}})- 优势:性能最佳、CDN 友好、服务器成本低
- 劣势:动态内容支持有限、构建时间长
- 适用:文档网站、营销页面、博客
-
SPA (单页应用)
// nuxt.config.tsexport default defineNuxtConfig({ssr: false})- 优势:用户体验好、服务器负载低、开发简单
- 劣势:SEO 不友好、首屏加载慢
- 适用:管理后台、用户仪表盘、游戏应用
示例说明
<!-- pages/index.vue - SSR 页面 -->
<template>
<div>
<h1>首页</h1>
<p>当前时间: {{ currentTime }}</p>
<ArticleList :articles="articles" />
</div>
</template>
<script setup>
// 服务端渲染时执行
const currentTime = new Date().toLocaleString()
const { data: articles } = await $fetch('/api/articles')
</script>
<!-- pages/blog/[slug].vue - SSG 页面 -->
<template>
<div>
<h1>{{ article.title }}</h1>
<div v-html="article.content"></div>
</div>
</template>
<script setup>
// 构建时预渲染
const route = useRoute()
const { data: article } = await $fetch(`/api/articles/${route.params.slug}`)
</script>
面试官视角
该题考察候选人对不同渲染模式的理解,是 Nuxt 开发的核心概念。通过此题可以引出性能优化、SEO 策略等更深层的技术点。
延伸阅读
什么是混合渲染,如何实现?
答案
核心概念
混合渲染允许在同一个 Nuxt 应用中,不同的页面使用不同的渲染模式,实现最优的性能和用户体验。
实现方式
-
页面级渲染模式
<!-- pages/index.vue - SSR --><template><div>首页内容</div></template><script setup>// 默认 SSR</script><!-- pages/admin.vue - SPA --><template><div>管理后台</div></template><script setup>// 指定为 SPA 模式definePageMeta({ssr: false})</script> -
路由级渲染模式
// nuxt.config.tsexport default defineNuxtConfig({nitro: {prerender: {routes: ['/', // 首页 SSG'/about', // 关于页面 SSG'/contact' // 联系页面 SSG]}}}) -
动态渲染模式
<!-- pages/products/[id].vue --><template><div><h1>{{ product.name }}</h1><p>{{ product.description }}</p></div></template><script setup>const route = useRoute()const productId = route.params.id// 根据产品类型决定渲染模式const { data: product } = await $fetch(`/api/products/${productId}`)// 热门产品使用 SSR,其他使用 SSGif (product.isPopular) {// SSR 模式} else {// SSG 模式}</script>
实际应用场景
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
prerender: {
routes: [
// 静态页面 - SSG
'/',
'/about',
'/contact',
'/privacy',
'/terms'
// 动态页面 - SSR
// 产品详情页、用户个人页面等
]
}
},
// 特定路由的渲染配置
routeRules: {
// 首页使用 SSG
'/': { prerender: true },
// 关于页面使用 SSG
'/about': { prerender: true },
// 产品页面使用 SSR
'/products/**': { ssr: true },
// 管理后台使用 SPA
'/admin/**': { ssr: false },
// API 路由
'/api/**': { cors: true }
}
})
性能优化策略
-
静态内容 SSG
<!-- pages/blog/[slug].vue --><template><div><h1>{{ post.title }}</h1><div v-html="post.content"></div></div></template><script setup>// 博客文章通常是静态内容,适合 SSGconst route = useRoute()const { data: post } = await $fetch(`/api/posts/${route.params.slug}`)</script> -
动态内容 SSR
<!-- pages/user/[id].vue --><template><div><h1>{{ user.name }}</h1><p>最后登录: {{ user.lastLogin }}</p></div></template><script setup>// 用户信息是动态的,适合 SSRconst route = useRoute()const { data: user } = await $fetch(`/api/users/${route.params.id}`)</script> -
交互应用 SPA
<!-- pages/dashboard.vue --><template><div><h1>用户仪表盘</h1><ChartComponent :data="chartData" /><RealTimeUpdates /></div></template><script setup>// 仪表盘需要实时交互,适合 SPAdefinePageMeta({ssr: false})</script>
配置最佳实践
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 首页和静态页面
'/': { prerender: true },
'/about': { prerender: true },
'/contact': { prerender: true },
// 动态内容页面
'/products/**': { ssr: true },
'/users/**': { ssr: true },
// 管理后台
'/admin/**': { ssr: false },
// API 路由
'/api/**': {
cors: true,
headers: { 'cache-control': 's-maxage=60' }
}
}
})
面试官视角
该题考察候选人对混合渲染的理解,是构建高性能应用的重要技术。通过此题可以引出性能优化、缓存策略等更深层的优化技巧。
延伸阅读
如何优化 Nuxt 应用的渲染性能?
答案
核心概念
Nuxt 应用性能优化需要从多个维度考虑,包括渲染模式选择、缓存策略、代码分割、资源优化等方面。
主要优化策略
-
渲染模式优化
- 静态内容使用 SSG
- 动态内容使用 SSR
- 交互应用使用 SPA
-
缓存策略
- 页面级缓存
- API 缓存
- 静态资源缓存
-
代码分割
- 路由级分割
- 组件级分割
- 第三方库分割
详细优化方案
-
页面级缓存
// nuxt.config.tsexport default defineNuxtConfig({routeRules: {// 静态页面长期缓存'/': {prerender: true,headers: { 'cache-control': 's-maxage=31536000' }},// 动态页面短期缓存'/products/**': {ssr: true,headers: { 'cache-control': 's-maxage=300' }},// 实时页面不缓存'/live/**': {ssr: true,headers: { 'cache-control': 'no-cache' }}}}) -
API 缓存优化
// server/api/products/[id].get.tsexport default defineEventHandler(async (event) => {const id = getRouterParam(event, 'id')// 使用缓存const cached = await useStorage('cache').getItem(`product:${id}`)if (cached) {return cached}// 获取数据const product = await getProduct(id)// 缓存数据await useStorage('cache').setItem(`product:${id}`, product, {ttl: 300 // 5分钟缓存})return product}) -
组件懒加载
<!-- 懒加载组件 --><template><div><h1>产品列表</h1><LazyProductCardv-for="product in products":key="product.id":product="product"/></div></template><script setup>// 懒加载组件,只在需要时加载const LazyProductCard = defineAsyncComponent(() =>import('~/components/ProductCard.vue'))</script> -
图片优化
<template><div><!-- 使用 NuxtImg 组件优化图片 --><NuxtImgsrc="/images/product.jpg"alt="产品图片"width="300"height="200"loading="lazy"placeholder/></div></template> -
代码分割配置
// nuxt.config.tsexport default defineNuxtConfig({build: {// 代码分割配置splitChunks: {layouts: true,pages: true,commons: true}},// 预加载关键资源app: {head: {link: [{ rel: 'preload', href: '/fonts/main.woff2', as: 'font', type: 'font/woff2', crossorigin: '' }]}}})
性能监控
// plugins/performance.client.ts
export default defineNuxtPlugin(() => {
// 性能监控
if (process.client) {
// 监控页面加载时间
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0]
console.log('页面加载时间:', perfData.loadEventEnd - perfData.loadEventStart)
})
// 监控 API 请求时间
const originalFetch = window.fetch
window.fetch = async (...args) => {
const start = performance.now()
const response = await originalFetch(...args)
const end = performance.now()
console.log(`API 请求时间: ${end - start}ms`)
return response
}
}
})
实际应用示例
<!-- pages/products/index.vue - 优化的产品列表页 -->
<template>
<div>
<h1>产品列表</h1>
<!-- 使用虚拟滚动优化长列表 -->
<VirtualList
:items="products"
:item-height="200"
:container-height="600"
>
<template #default="{ item }">
<LazyProductCard :product="item" />
</template>
</VirtualList>
<!-- 分页加载 -->
<button
v-if="hasMore"
@click="loadMore"
:disabled="loading"
>
{{ loading ? '加载中...' : '加载更多' }}
</button>
</div>
</template>
<script setup>
// 分页加载数据
const page = ref(1)
const products = ref([])
const hasMore = ref(true)
const loading = ref(false)
const loadMore = async () => {
if (loading.value) return
loading.value = true
try {
const { data: newProducts } = await $fetch(`/api/products?page=${page.value}`)
products.value.push(...newProducts)
page.value++
hasMore.value = newProducts.length > 0
} finally {
loading.value = false
}
}
// 初始加载
await loadMore()
</script>
面试官视角
该题考察候选人对性能优化的理解,是构建高质量应用的重要技能。通过此题可以引出缓存策略、代码分割、资源优化等更深层的优化技巧。
延伸阅读