Vue.js SSR 編寫通用代碼

2021-01-07 16:00 更新

在進(jìn)一步介紹之前,讓我們花點(diǎn)時(shí)間來(lái)討論編寫"通用"代碼時(shí)的約束條件 - 即運(yùn)行在服務(wù)器和客戶端的代碼。由于用例和平臺(tái) API 的差異,當(dāng)運(yùn)行在不同環(huán)境中時(shí),我們的代碼將不會(huì)完全相同。所以這里我們將會(huì)闡述你需要理解的關(guān)鍵事項(xiàng)。

服務(wù)器上的數(shù)據(jù)響應(yīng)

在純客戶端應(yīng)用程序 (client-only app) 中,每個(gè)用戶會(huì)在他們各自的瀏覽器中使用新的應(yīng)用程序?qū)嵗?。?duì)于服務(wù)器端渲染,我們也希望如此:每個(gè)請(qǐng)求應(yīng)該都是全新的、獨(dú)立的應(yīng)用程序?qū)嵗?,以便不?huì)有交叉請(qǐng)求造成的狀態(tài)污染 (cross-request state pollution)。

因?yàn)閷?shí)際的渲染過(guò)程需要確定性,所以我們也將在服務(wù)器上“預(yù)取”數(shù)據(jù) ("pre-fetching" data) - 這意味著在我們開始渲染時(shí),我們的應(yīng)用程序就已經(jīng)解析完成其狀態(tài)。也就是說(shuō),將數(shù)據(jù)進(jìn)行響應(yīng)式的過(guò)程在服務(wù)器上是多余的,所以默認(rèn)情況下禁用。禁用響應(yīng)式數(shù)據(jù),還可以避免將「數(shù)據(jù)」轉(zhuǎn)換為「響應(yīng)式對(duì)象」的性能開銷。

組件生命周期鉤子函數(shù)

由于沒(méi)有動(dòng)態(tài)更新,所有的生命周期鉤子函數(shù)中,只有 beforeCreatecreated 會(huì)在服務(wù)器端渲染 (SSR) 過(guò)程中被調(diào)用。這就是說(shuō)任何其他生命周期鉤子函數(shù)中的代碼(例如 beforeMountmounted),只會(huì)在客戶端執(zhí)行。

此外還需要注意的是,你應(yīng)該避免在 beforeCreatecreated 生命周期時(shí)產(chǎn)生全局副作用的代碼,例如在其中使用 setInterval 設(shè)置 timer。在純客戶端 (client-side only) 的代碼中,我們可以設(shè)置一個(gè) timer,然后在 beforeDestroydestroyed 生命周期時(shí)將其銷毀。但是,由于在 SSR 期間并不會(huì)調(diào)用銷毀鉤子函數(shù),所以 timer 將永遠(yuǎn)保留下來(lái)。為了避免這種情況,請(qǐng)將副作用代碼移動(dòng)到 beforeMountmounted 生命周期中。

訪問(wèn)特定平臺(tái)(Platform-Specific) API

通用代碼不可接受特定平臺(tái)的 API,因此如果你的代碼中,直接使用了像 windowdocument,這種僅瀏覽器可用的全局變量,則會(huì)在 Node.js 中執(zhí)行時(shí)拋出錯(cuò)誤,反之也是如此。

對(duì)于共享于服務(wù)器和客戶端,但用于不同平臺(tái) API 的任務(wù)(task),建議將平臺(tái)特定實(shí)現(xiàn)包含在通用 API 中,或者使用為你執(zhí)行此操作的 library。例如,axios 是一個(gè) HTTP 客戶端,可以向服務(wù)器和客戶端都暴露相同的 API。

對(duì)于僅瀏覽器可用的 API,通常方式是,在「純客戶端 (client-only)」的生命周期鉤子函數(shù)中惰性訪問(wèn) (lazily access) 它們。

請(qǐng)注意,考慮到如果第三方 library 不是以上面的通用用法編寫,則將其集成到服務(wù)器渲染的應(yīng)用程序中,可能會(huì)很棘手。你可能要通過(guò)模擬 (mock) 一些全局變量來(lái)使其正常運(yùn)行,但這只是 hack 的做法,并且可能會(huì)干擾到其他 library 的環(huán)境檢測(cè)代碼。

自定義指令

大多數(shù)自定義指令直接操作 DOM,因此會(huì)在服務(wù)器端渲染 (SSR) 過(guò)程中導(dǎo)致錯(cuò)誤。有兩種方法可以解決這個(gè)問(wèn)題:

  1. 推薦使用組件作為抽象機(jī)制,并運(yùn)行在「虛擬 DOM 層級(jí)(Virtual-DOM level)」(例如,使用渲染函數(shù)(render function))。

  1. 如果你有一個(gè)自定義指令,但是不是很容易替換為組件,則可以在創(chuàng)建服務(wù)器 renderer 時(shí),使用 directives 選項(xiàng)所提供"服務(wù)器端版本(server-side version)"。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)