[Lv3] SSR 實作難題與解決方案
在 SSR 實作過程中,常見的難題與解決方案:Hydration Mismatch、環境變數處理、第三方套件相容性、效能優化等。
📋 面試情境題
Q: 在實作 SSR 時,有遇到 哪些難題?如何解決?
這是面試中經常會被問到的問題,面試官想了解:
- 實際經驗:是否真的實作過 SSR
- 問題解決能力:遇到問題時的思考過程
- 技術深度:對 SSR 原理的理解程度
- 最佳實踐:是否有採用業界標準做法
難題 1:Hydration Mismatch 錯誤
問題描述
錯誤訊息:
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content.
發生原因:
- Server Side 渲染的 HTML 與 Client Side 渲染的 HTML 不一致
- 常見於使用瀏覽器專用 API(
window、document、localStorage等) - 時間相關的內容(如:
new Date())在 Server 和 Client 執行時間不同
解決 方案
方案 1: 使用 ClientOnly 組件
適用場景: 組件只在客戶端渲染
<template>
<div>
<h1>主要內容(SSR)</h1>
<ClientOnly>
<BrowserOnlyComponent />
<template #fallback>
<div>載入中...</div>
</template>
</ClientOnly>
</div>
</template>
優點:
- ✅ 簡單直接
- ✅ Nuxt 內建支援
缺點:
- ⚠️ 該部分內容不會在 SSR 中渲染
- ⚠️ 可能影響 SEO
方案 2: 使用 process.client 檢查
適用場景: 條件式渲染客戶端專用內容
<script setup lang="ts">
const userAgent = ref('');
onMounted(() => {
// 只在客戶端執行
if (process.client) {
userAgent.value = navigator.userAgent;
}
});
</script>
<template>
<div>
<p v-if="userAgent">User Agent: {{ userAgent }}</p>
</div>
</template>
關鍵點:
- ✅ 使用
process.client檢查執行環境 - ✅ 避免在 Server Side 存取瀏覽器 API
方案 3: 使用 onMounted Hook
適用場景: 需要在客戶端執行的初始化邏輯
<script setup lang="ts">
const isClient = ref(false);
onMounted(() => {
isClient.value = true;
// 客戶端專用的初始化邏輯
initializeClientOnlyFeature();
});
</script>
<template>
<div>
<div v-if="isClient">客戶端內容</div>
<div v-else>伺服器端內容(或載入中)</div>
</div>
</template>