2025年9月29日 星期一

資深前端工程師面試指南:Nuxt 3 生命週期與 SSR、CSR、SSG 渲染策略

🚀 資深前端面試終極指南: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)

      TypeScript
      export default defineEventHandler((event) => {
        // 僅在伺服器端執行,用於日誌紀錄或 Header 注入
        console.log(`[Request Log]: ${getRequestURL(event)}`);
      });
      
  • (3) 資料預取 (useAsyncData / useFetch):這是最關鍵的一步。Nuxt 會在伺服器執行非同步請求,並將結果「序列化」進 HTML(透過 window.__NUXT__)。

  • (4) HTML 生成與 ResponseuseHead 配置 Meta,最終將 HTML 字串傳送至瀏覽器。

2. 客戶端生命週期 (Client-side Lifecycle)

  • (1) Hydration (注水):Vue 在瀏覽器接管靜態 HTML,將其轉為可互動的響應式組件。資深必考點:Hydration Mismatch 排查。

  • (2) 組件掛載:執行 onMounted,此時才可安全存取 windowdocument


二、 渲染策略深度實戰與範例

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)

TypeScript
// 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 同步雙端狀態:

    TypeScript
    const time = useState('time', () => new Date().toISOString());
    
  • 使用 <ClientOnly> 包裹變動頻繁的區塊。

2. 效能優化:Payload 與 Memory Cache

  • Payload 縮減:避免在 useFetch 回傳整個大型物件,應使用 picktransform 過濾。

  • Lazy Fetching

    TypeScript
    const { data } = await useFetch('/api/data', { lazy: true });
    // 使用 pending 狀態展示 Skeleton 螢幕
    

四、 模擬面試問答 (Q&A)

Q:如何決定一個專案該用 SSR 還是 CSR

A:資深工程師應從三個維度評估:

  1. SEO 權重:首頁、產品頁、文章頁必須 SSR/SSG。

  2. 伺服器成本:若預算有限且內容高度個人化(如 Dashboard),應選 CSR。

  3. 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 達到最佳平衡。

沒有留言:

張貼留言

📦 LogiFlow WMS:打造 SaaS 多租戶倉儲管理系統的技術實踐

📦 LogiFlow WMS:打造 SaaS 多租戶倉儲管理系統的技術實踐 在企業數位化的浪潮下,倉儲管理系統 (WMS) 不再只是單一公司的內部工具,而是需要支援 多租戶 (Multi-Tenant) 的 SaaS 架構。這意味著系統必須在共享基礎設施的同時,保有嚴格的資...