2025年9月29日 星期一

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

 

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

在資深前端工程師的面試中,Nuxt 3 是一個熱門話題,尤其是其生命週期以及伺服器端渲染 (SSR)、客戶端渲染 (CSR) 和靜態生成 (SSG) 的應用場景。這些議題不僅考驗對框架的理解,還涉及架構設計、效能優化與 SEO 等實務能力。本文整合了 Nuxt 3 的生命週期與三種渲染方式的常見面試題目,提供深入解析、程式碼範例、場景選擇建議與潛在陷阱,幫助你在面試中展現專業能力,並為實際專案選擇合適的渲染策略。


一、Nuxt 3 生命週期深入解析

Nuxt 3 的生命週期涵蓋伺服器端與客戶端階段,結合 Vue 3 的 Composition API 和 Nitro 引擎(Nuxt 的伺服器引擎)。以下按執行順序解析,並針對面試提供實用範例。

1. 伺服器端生命週期(SSR 或混合模式)

伺服器端生命週期在 Nuxt 處理請求時執行,適用於 SSR 或混合模式。

(1) 伺服器啟動與初始化

  • 觸發時機:伺服器啟動或收到請求。
  • 關鍵點:Nuxt 載入 nuxt.config.ts,初始化模組、插件與 middleware。Nitro 引擎啟動,處理伺服器端路由。
  • 面試問題:如何在 Nuxt 中配置全域 middleware?
  • 回答
    • server/middleware/nuxt.config.ts 定義全域 middleware,用於日誌或請求攔截。
    • 範例程式碼(server/middleware/log.ts):
      export default defineEventHandler((event) => {
        console.log(`Request: ${event.node.req.url}`);
      });
      
    • 實務:用於追蹤 API 請求或設定 CORS。陷阱:避免阻塞請求導致效能下降。

(2) 伺服器端 Middleware

  • 觸發時機:請求到達路由前。
  • 關鍵點:全域或頁面級 middleware,檢查權限或重導。
  • 面試問題:如何使用 middleware 實現權限控制?
  • 回答
    • 定義路由 middleware,檢查 cookie 或 token,導向登入頁。
    • 範例程式碼(middleware/auth.ts):
      export default defineNuxtRouteMiddleware((to, from) => {
        const user = useCookie('token');
        if (!user.value && to.path !== '/login') {
          return navigateTo('/login');
        }
      });
      
    • 實務:搭配 @nuxtjs/auth-next 模組。陷阱:SSR 中避免使用客戶端專用 API(如 window)。

(3) 資料預取(useAsyncData / useFetch)

  • 觸發時機:頁面渲染前。
  • 關鍵點useAsyncDatauseFetch 預取資料,序列化後傳至客戶端。
  • 面試問題:如何避免重複資料請求?
  • 回答
    • 使用 key 參數快取資料,確保唯一性。
    • 範例程式碼(pages/index.vue):
      <script setup>
      const { data: posts } = await useFetch('/api/posts', { key: 'posts' });
      </script>
      
    • 實務:用於 API 呼叫或資料庫查詢。陷阱:重複 key 導致快取覆蓋。

(4) 伺服器端渲染

  • 觸發時機:生成 HTML。
  • 關鍵點:Nuxt 使用 Vue 的伺服器渲染器,useHead 配置 meta tags 提升 SEO。
  • 面試問題:如何確保 SSR 的 SEO 效果?
  • 回答
    • 使用 useHead 動態生成 meta,整合 @nuxtjs/sitemap
    • 範例程式碼
      <script setup>
      useHead({
        title: 'Home',
        meta: [{ name: 'description', content: 'SSR page' }],
      });
      </script>
      
    • 實務:設置 canonical links 避免重複內容。陷阱:伺服器與客戶端 meta 不一致。

(5) 伺服器回應

  • 觸發時機:HTML 傳送至客戶端。
  • 關鍵點:Nitro 回傳渲染結果與序列化資料。

2. 客戶端生命週期

客戶端生命週期在瀏覽器接收 HTML 後執行,涵蓋 hydration 和 Vue 組件邏輯。

(1) Hydration

  • 觸發時機:客戶端載入 HTML。
  • 關鍵點:Vue 將靜態 HTML 轉為響應式應用,恢復伺服器序列化資料。
  • 面試問題:如何避免 hydration mismatch?
  • 回答
    • 確保伺服器與客戶端邏輯一致,使用 onServerPrefetchprocess.client
    • 範例程式碼
      <script setup>
      const time = ref('');
      if (process.client) {
        time.value = new Date().toISOString();
      }
      </script>
      
    • 陷阱:條件渲染(如隨機數)導致不一致。

(2) Vue 組件生命週期

  • 觸發時機:組件創建、更新、銷毀。
  • 關鍵點:使用 Composition API 的 onMountedonUnmounted 等。
  • 範例程式碼
    <script setup>
    onMounted(() => {
      console.log('Client-side mounted');
    });
    </script>
    

(3) 客戶端專用資料獲取

  • 觸發時機:客戶端渲染時。
  • 關鍵點useFetchserver: false 僅客戶端執行。
  • 範例程式碼
    <script setup>
    const { data } = await useFetch('/api/user', { server: false });
    </script>
    

(4) 客戶端插件

  • 觸發時機:客戶端初始化。
  • 範例程式碼(plugins/analytics.client.ts):
    export default defineNuxtPlugin((nuxtApp) => {
      window.addEventListener('click', () => console.log('Track click'));
    });
    

3. Nuxt 鉤子(Hooks)

  • 伺服器端鉤子:如 render:response,用於自訂回應。
  • 客戶端鉤子:如 page:finish,用於頁面載入後邏輯。
  • 範例
    export default defineNuxtPlugin((nuxtApp) => {
      nuxtApp.hook('page:finish', () => console.log('Page loaded'));
    });
    

二、伺服器端渲染 (SSR)、靜態生成 (SSG) 與客戶端渲染 (CSR)

選擇渲染方式影響 SEO、效能與開發複雜度。以下解析三者的原理、優缺點與場景。

1. 伺服器端渲染 (SSR)

定義:伺服器生成完整 HTML,客戶端 hydrate 為互動應用。Nuxt 3 預設 SSR。
流程

  • 伺服器執行 middleware 和 useFetch,生成 HTML。
  • 客戶端 hydrate,綁定事件。
    優點
  • SEO 友好:爬蟲可解析。
  • 首屏快速:HTML 即時回傳。
  • 動態內容:適合頻繁更新。
    缺點
  • 伺服器負載高。
  • Hydration 增加客戶端計算。
    場景:電商產品頁(動態庫存)、新聞網站(即時內容)。
    面試問題:如何優化 SSR 負載?
    回答
  • 使用 Nitro 快取或 CDN(如 Cloudflare)。
  • 範例(nuxt.config.ts):
    export default defineNuxtConfig({
      nitro: {
        compress: true,
        render: { cache: { maxAge: 3600 } },
      },
    });
    

2. 靜態生成 (SSG)

定義:建置時生成靜態 HTML,部署至 CDN。透過 nuxt generate 實現。
流程

  • 建置時爬取路由,生成 HTML。
  • 客戶端直接載入靜態檔案,隨後 hydrate。
    優點
  • 高效能:CDN 傳遞快速。
  • 低成本:無需伺服器。
  • SEO 優秀:預生成 HTML。
    缺點
  • 不適合動態內容。
  • 建置時間隨頁面增加而延長。
    場景:部落格、公司官網、行銷頁面。
    面試問題:如何在 SSG 中加入動態內容?
    回答
  • 客戶端用 useFetch 補充資料。
  • 範例
    <script setup>
    const { data } = await useFetch('/api/comments', { server: false });
    </script>
    

3. 客戶端渲染 (CSR)

定義:瀏覽器渲染 HTML,Nuxt 設 ssr: false 或頁面級 definePageMeta({ ssr: false })
流程

  • 載入空 HTML 和 JS bundle。
  • Vue 執行渲染與資料獲取。
    優點
  • 開發簡單:無伺服器邏輯。
  • 低伺服器成本:僅需靜態主機。
    缺點
  • SEO 差:爬蟲難解析。
  • 首屏慢:需下載 JS。
    場景:內部 dashboard、即時聊天應用。
    面試問題:如何改善 CSR 首屏速度?
    回答
  • 使用 lazy loading 與 code-splitting。
  • 範例
    <script setup>
    const LazyComponent = defineAsyncComponent(() => import('./HeavyComponent.vue'));
    </script>
    

三、實務應用與範例

1. SSR:電商產品頁

需求:動態庫存與 SEO。

<script setup>
useHead({
  title: 'Product Page',
  meta: [{ name: 'description', content: 'Dynamic product' }],
});
const route = useRoute();
const { data: product } = await useFetch(`/api/products/${route.params.id}`);
</script>
<template>
  <div>
    <h1>{{ product.name }}</h1>
    <p>Stock: {{ product.stock }}</p>
  </div>
</template>

2. SSG:部落格文章

需求:快速載入與 SEO。

<script setup>
useHead({
  title: 'Blog Post',
  meta: [{ name: 'description', content: 'Static content' }],
});
const { data: post } = await useAsyncData('post', () => $fetch('/api/posts/1'));
</script>
<template>
  <article>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
  </article>
</template>

3. CSR:管理 dashboard

需求:高互動,無 SEO。

<script setup>
definePageMeta({ ssr: false });
const { data: metrics } = await useFetch('/api/metrics', { server: false });
</script>
<template>
  <div>
    <h1>Dashboard</h1>
    <div v-if="metrics">{{ metrics.summary }}</div>
  </div>
</template>

四、潛在陷阱與最佳實踐

  1. SSR 陷阱

    • Hydration mismatch:伺服器與客戶端渲染不一致。
    • 解決:使用 onServerPrefetchprocess.client
    • 範例
      <script setup>
      const time = ref('');
      onServerPrefetch(() => {
        time.value = new Date().toISOString();
      });
      </script>
      
  2. SSG 陷阱

    • 建置時間長:過多動態路由。
    • 解決:限制 prerender 路由或使用增量靜態生成 (ISG)。
  3. CSR 陷阱

    • SEO 問題:動態內容無法爬取。
    • 解決:混合 SSR 頁面(如首頁)。

最佳實踐

  • 混合模式:頁面級配置(如首頁 SSR,dashboard CSR)。
  • 快取:Nitro 記憶體快取或 CDN。
  • 監控:Lighthouse 分析首屏與 SEO。

五、模擬面試問題與回答

  1. 問題:如何決定使用 SSR、SSG 或 CSR?
    回答:依 SEO、動態性與效能需求選擇。電商用 SSR 確保動態更新;部落格用 SSG 提升速度;內部工具用 CSR 簡化開發。

  2. 問題:如何在 SSR 中處理 API 失敗?
    回答

    • 使用 useFetch 的 error 屬性,提供 fallback 或錯誤頁。
    • 範例
      <script setup>
      const { data, error } = await useFetch('/api/data');
      if (error.value) {
        throw createError({ statusCode: 500, message: 'API Failed' });
      }
      </script>
      
  3. 問題:如何在 Nuxt 生命週期中優化資料預取?
    回答

    • 使用 useAsyncData 快取,設定唯一 key,減少重複請求。
    • 範例
      <script setup>
      const { data } = await useAsyncData('unique-key', () => $fetch('/api/data'));
      </script>
      

六、總結

Nuxt 3 的生命週期整合伺服器端與客戶端,提供 middleware、資料預取與鉤子等工具,支援 SSR、SSG 和 CSR 三種渲染方式。SSR 適合動態內容與 SEO,SSG 適合靜態網站,CSR 適合互動應用。資深工程師應熟練配置混合模式,優化效能與 SEO,並避免 hydration mismatch 等陷阱。面試時,結合實務案例(如電商或 dashboard)展示技術深度,將大大提升說服力。

推薦資源

沒有留言:

張貼留言

熱門文章