前言
接著上一篇文章vue 2.0服務(wù)端渲染從零開始(一)伤溉,本篇主要介紹如何編寫通用代碼躏尉。
編寫通用代碼
編寫通用代碼時(shí)的約束條件:即運(yùn)行在服務(wù)器和客戶端的代碼尤溜,由于用例和平臺(tái)API的差異一死,當(dāng)運(yùn)行在不同環(huán)境中時(shí)钞诡,我們的代碼將不會(huì)完全相同周伦。
在Vue.js 服務(wù)器端渲染指南--編寫通用代碼中詳細(xì)的介紹了需要注意的幾個(gè)方面:
- 服務(wù)器上的數(shù)據(jù)響應(yīng)
- 獨(dú)立的應(yīng)用程序?qū)嵗?/li>
- 禁用數(shù)據(jù)響應(yīng)
- 組件生命周期鉤子函數(shù)
- 只有
beforeCreate
和create
會(huì)在服務(wù)端渲染(SSR)過程中被調(diào)用夕春。 - 副作用代碼移動(dòng)到
beforeMount
或mounted
生命周期中。
- 只有
- 訪問特定平臺(tái)API
- 僅瀏覽器可用的全局變量
window
或document
专挪,在純客戶端的生命周期鉤子函數(shù)中惰性訪問它們及志。 - 盡可能使用通用API,例如axios可以向服務(wù)器和客戶端都暴露相同的API
- 僅瀏覽器可用的全局變量
- 自定義指令
- 推薦使用組件作為抽象機(jī)制寨腔,并運(yùn)行在「虛擬 DOM 層級(jí)(Virtual-DOM level)」(例如使用渲染函數(shù)
render function
) - 如果自定義指令不是很容易替換為組件速侈,則可以在創(chuàng)建服務(wù)器renderer時(shí),使用
directives
選項(xiàng)提供的"服務(wù)器端版本"
- 推薦使用組件作為抽象機(jī)制寨腔,并運(yùn)行在「虛擬 DOM 層級(jí)(Virtual-DOM level)」(例如使用渲染函數(shù)
避免狀態(tài)單例
同樣是單例對(duì)象(vue實(shí)例)迫卢,在純客戶端代碼時(shí)倚搬,vue實(shí)例在組件創(chuàng)建是生成,在組件銷毀后跟著從內(nèi)存中清除乾蛤。
但是Node.js服務(wù)器是一個(gè)長(zhǎng)期運(yùn)行的進(jìn)程每界。創(chuàng)建的vue實(shí)例將一直留存在內(nèi)存中,導(dǎo)致它被每個(gè)傳入的請(qǐng)求共享幻捏,這樣很容易導(dǎo)致交叉請(qǐng)求狀態(tài)污染盆犁。
因此,我們不應(yīng)該直接創(chuàng)建一個(gè)應(yīng)用程序?qū)嵗劬牛菓?yīng)該暴露一個(gè)可以重復(fù)執(zhí)行的工廠函數(shù)谐岁,為每個(gè)請(qǐng)求創(chuàng)建新的應(yīng)用程序?qū)嵗?/p>
之前基本示例中的寫法(直接創(chuàng)建):
const app = new Vue({
data: {
url: req.url
},
template: '<div>訪問的url是{{url}}</div>'
});
工廠模式:
app.js
const Vue = require('vue')
module.exports = function createApp (context) {
return new Vue({
data: {
url: context.url
},
template: '<div>訪問的 URL 是:{{ url }}</div>'
})
}
server.js
const createApp = require('./app')
const app = createApp(context)
完整示例
戳我
請(qǐng)注意分支:dev_2分支
result.png