1. SSR與CSR的區別
1.1.?SSR的原理
服務端渲染(SSR)是在服務器端將 Vue 組件渲染為 HTML 字符串,并將其發送給客戶端。這種方式與客戶端渲染(CSR)不同,后者是在瀏覽器中執行 JavaScript 來生成 HTML。
在 SSR 中,客戶端第一次訪問頁面時,服務器會根據請求路徑渲染對應的 HTML 頁面,這有利于提升首屏加載速度和 SEO 性能。之后,客戶端還需要進行“激活”,通過 Vue 的?hydrate 方法讓已經渲染好的 HTML 具備動態交互能力。而 CSR 則是先加載靜態 HTML 框架,之后由客戶端完成所有頁面的 JavaScript 渲染。
1.2. 兩者的主要區別
SEO:SSR 在服務器端生成完整的 HTML,利于搜索引擎爬取,而 CSR 生成的 HTML 需要等到 JavaScript 執行完畢后才可用。
性能:SSR 的首屏渲染速度快,但會增加服務器負載;CSR 依賴瀏覽器的計算能力,但可以降低服務器的壓力。
安全:SSR 可以更好地控制輸出內容,減少 XSS 攻擊的風險。
2.?SSR 中如何解決首屏數據獲取問題
在 Vue SSR 中,首屏數據的獲取需要提前在服務器端完成。常用的解決方案是在組件中定義一個 asyncData 方法,專門用于數據預取。這個方法在組件渲染之前調用,服務器端會在渲染 HTML 之前獲取數據并將其注入到組件的 props 中。
2.1. 具體步驟
1. 在服務器端,在 SSR 渲染函數中,先調用組件的 asyncData 方法獲取數據,再將數據注入到 Vue 組件的 props。
2.?在客戶端,Vue 會利用 hydrate 方法進行激活,接管服務器端生成的 HTML。客戶端還會將服務器預取的數據作為初始狀態傳遞,避免重復請求。
數據預取的關鍵在于服務器端需要等待數據加載完畢再渲染頁面,以保證返回給客戶端的 HTML 包含實際的數據。
// 組件中定義 asyncData 方法
export default {async asyncData({ app }) {const data = await fetchData();return { data };},render(h) {return h('div', this.data);}
};
3.?處理路由和狀態同步問題
在 Vue SSR 中,路由和狀態的同步非常重要。為了確保服務器和客戶端渲染結果一致,必須在服務器端渲染時同步路由和狀態。常用的做法包括:
3.1. 路由同步
在服務器端渲染時,服務器會根據用戶的請求 URL 手動調用 router.push() 將路由切換到正確的頁面,然后等待 router.isReady() 確保所有異步路由組件加載完畢后,再進行服務器端渲染。客戶端同樣會根據當前 URL 初始化路由。
// 服務器端路由同步
app.use((req, res, next) => {router.push(req.path, (err, url) => {if (err) {res.status(404).end();} else {app.context.url = url;next();}});
});
3.2. 狀態同步
在 SSR 場景中,服務器端渲染后的狀態(如 Pinia 的 store 狀態)需要傳遞到客戶端。這通常是通過將狀態序列化并嵌入到 HTML 中,客戶端在激活時會使用這些初始狀態,避免再次請求數據。
// 狀態同步
const store = createPinia();
const app = createApp({store,render: () => h(App)
});app.mount('#app', () => {const state = store.state.value;document.getElementById('state').textContent = JSON.stringify(state);
});
4. 總結
Vue 3 的服務端渲染(SSR)和客戶端渲染(CSR)各有優缺點。SSR 提升了首屏加載速度和 SEO 性能,但增加了服務器負載;CSR 則依賴瀏覽器的計算能力,降低了服務器壓力。在實際應用中,開發者需要根據項目需求選擇合適的渲染方式,并采取相應的解決方案來處理首屏數據獲取和路由及狀態同步問題,以確保應用的性能和用戶體驗。