🚀 資深前端面試終極指南:Nuxt 3 生命週期與全場景渲染策略 (SSR, CSR, SSG, SWR)
在資深職位的面試中,Nuxt 3 的考點通常圍繞在效能瓶頸、狀態同步、SEO 優化與伺服器引擎 (Nitro) 的配置。本文將從生命週期底層邏輯出發,延伸至複雜的渲染架構設計。
一、 Nuxt 3 生命週期:從伺服器到客戶端的完整路徑
資深工程師必須區分「程式碼是在 Node.js 執行」還是「在瀏覽器執行」。
1. 伺服器端生命週期 (Server-side Lifecycle)
當請求進入 Nitro 引擎時:
(1) Nitro 啟動與初始化:載入
nuxt.config.ts,初始化模組 (Modules) 與插件 (Plugins)。(2) Server Middleware:在處理路由前攔截請求。
實務範例 (server/middleware/logger.ts):
TypeScriptexport default defineEventHandler((event) => { // 僅在伺服器端執行,用於日誌紀錄或 Header 注入 console.log(`[Request Log]: ${getRequestURL(event)}`); });
(3) 資料預取 (useAsyncData / useFetch):這是最關鍵的一步。Nuxt 會在伺服器執行非同步請求,並將結果「序列化」進 HTML(透過
window.__NUXT__)。(4) HTML 生成與 Response:
useHead配置 Meta,最終將 HTML 字串傳送至瀏覽器。
2. 客戶端生命週期 (Client-side Lifecycle)
(1) Hydration (注水):Vue 在瀏覽器接管靜態 HTML,將其轉為可互動的響應式組件。資深必考點:Hydration Mismatch 排查。
(2) 組件掛載:執行
onMounted,此時才可安全存取window或document。
二、 渲染策略深度實戰與範例
Nuxt 3 真正的強大在於其 Hybrid Rendering (混合渲染) 能力。
1. SSR (伺服器端渲染):動態內容與 SEO
適用場景:電商商品頁、新聞列表。
進階範例:處理強型別與 API 錯誤。
<script setup lang="ts">
interface Product {
id: string;
name: string;
price: number;
description: string;
}
const route = useRoute();
const productId = route.params.id as string;
// 使用 useFetch 的進階配置
// key: 確保路由變動時資料正確更新
// lazy: 配合 <Suspense> 或自定義 Loading 提升體驗
const { data: product, error } = await useFetch<Product>(`/api/products/${productId}`, {
key: `product-${productId}`,
pick: ['name', 'price', 'description'], // 只取需要的欄位,優化 Payload
onResponseError({ response }) {
// 伺服器端錯誤處理
console.error('Fetch Error:', response.status);
}
});
// 若 API 失敗,直接觸發 Nuxt 錯誤頁面 (SEO 友好)
if (error.value || !product.value) {
throw createError({ statusCode: 404, statusMessage: '商品不存在', fatal: true });
}
useHead({
title: product.value.name,
meta: [{ name: 'description', content: product.value.description }]
});
</script>
<template>
<div>
<h1>{{ product?.name }}</h1>
<p>價格:{{ product?.price }}</p>
</div>
</template>
2. SSG (靜態生成) + SWR:極致效能
適用場景:部落格、官網。利用 SWR (Stale-While-Revalidate)。
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/blog/**': { static: true }, // 靜態生成
'/api/static-proxy/**': { swr: 3600 } // 背景每小時更新一次緩存
}
});
3. CSR (客戶端渲染):內部管理後台
適用場景:Dashboard、需權限驗證且無 SEO 需求的頁面。
<script setup lang="ts">
// 關閉此頁面的伺服器端渲染,減少伺服器負擔
definePageMeta({ ssr: false });
// server: false 確保此請求僅在瀏覽器端發出
const { data: adminData } = await useFetch('/api/admin/stats', {
server: false,
headers: { Authorization: `Bearer ${useCookie('token').value}` }
});
</script>
<template>
<div v-if="adminData">
<LazyAdminChart :stats="adminData" />
</div>
</template>
三、 資深面試陷阱與最佳實踐
1. Hydration Mismatch (伺服器與客戶端不一致)
陷阱:在 template 中使用 new Date() 或隨機數。
解決方案:
使用
useState同步雙端狀態:TypeScriptconst time = useState('time', () => new Date().toISOString());使用
<ClientOnly>包裹變動頻繁的區塊。
2. 效能優化:Payload 與 Memory Cache
Payload 縮減:避免在
useFetch回傳整個大型物件,應使用pick或transform過濾。Lazy Fetching:
TypeScriptconst { data } = await useFetch('/api/data', { lazy: true }); // 使用 pending 狀態展示 Skeleton 螢幕
四、 模擬面試問答 (Q&A)
A:資深工程師應從三個維度評估:
SEO 權重:首頁、產品頁、文章頁必須 SSR/SSG。
伺服器成本:若預算有限且內容高度個人化(如 Dashboard),應選 CSR。
TTFB (Time to First Byte):若追求極致秒開且內容更新不頻繁,應選 SSG 配合 CDN。
Q:Nuxt 3 的 useAsyncData 為什麼要帶 key?
A:因為在 SSR 過程中,Nuxt 需要將資料標記並序列化到 HTML。若沒有唯一的 key(或 key 沒隨路由參數變化),當客戶端接管時,會無法正確對應到對應的資料片段,導致重新發起 API 請求,喪失 SSR 優勢。
五、 總結
資深前端在處理 Nuxt 3 時,必須展現出對 「混合架構」 的掌控力。
利用 Nitro Route Rules 進行精細化渲染控制。
利用 TypeScript 確保資料傳輸的安全性。
利用 生命週期鉤子 解決 Hydration 異常,確保使用者體驗與 SEO 達到最佳平衡。
沒有留言:
張貼留言