雖然 Vue 的服務(wù)器端渲染 (SSR) 相當快速,但是由于創(chuàng)建組件實例和虛擬 DOM 節(jié)點的開銷,無法與純基于字符串拼接 (pure string-based) 的模板的性能相當。在 SSR 性能至關(guān)重要的情況下,明智地利用緩存策略,可以極大改善響應(yīng)時間并減少服務(wù)器負載。
在大多數(shù)情況下,服務(wù)器渲染的應(yīng)用程序依賴于外部數(shù)據(jù),因此本質(zhì)上頁面內(nèi)容是動態(tài)的,不能持續(xù)長時間緩存。然而,如果內(nèi)容不是用戶特定 (user-specific)(即對于相同的 URL,總是為所有用戶渲染相同的內(nèi)容),我們可以利用名為 micro-caching 的緩存策略,來大幅度提高應(yīng)用程序處理高流量的能力。
這通常在 Nginx 層完成,但是我們也可以在 Node.js 中實現(xiàn)它:
const microCache = LRU({
max: 100,
maxAge: 1000 // 重要提示:條目在 1 秒后過期。
})
const isCacheable = req => {
// 實現(xiàn)邏輯為,檢查請求是否是用戶特定(user-specific)。
// 只有非用戶特定 (non-user-specific) 頁面才會緩存
}
server.get('*', (req, res) => {
const cacheable = isCacheable(req)
if (cacheable) {
const hit = microCache.get(req.url)
if (hit) {
return res.end(hit)
}
}
renderer.renderToString((err, html) => {
res.end(html)
if (cacheable) {
microCache.set(req.url, html)
}
})
})
由于內(nèi)容緩存只有一秒鐘,用戶將無法查看過期的內(nèi)容。然而,這意味著,對于每個要緩存的頁面,服務(wù)器最多只能每秒執(zhí)行一次完整渲染。
vue-server-renderer
內(nèi)置支持組件級別緩存 (component-level caching)。要啟用組件級別緩存,你需要在創(chuàng)建 renderer 時提供具體緩存實現(xiàn)方式(cache implementation) 。典型做法是傳入 lru-cache :
const LRU = require('lru-cache')
const renderer = createRenderer({
cache: LRU({
max: 10000,
maxAge: ...
})
})
然后,你可以通過實現(xiàn) serverCacheKey
函數(shù)來緩存組件。
export default {
name: 'item', // 必填選項
props: ['item'],
serverCacheKey: props => props.item.id,
render (h) {
return h('div', this.item.id)
}
}
請注意,可緩存組件還必須定義一個唯一的 name
選項。通過使用唯一的名稱,每個緩存鍵 (cache key) 對應(yīng)一個組件:你無需擔心兩個組件返回同一個 key。
serverCacheKey
返回的 key 應(yīng)該包含足夠的信息,來表示渲染結(jié)果的具體情況。如果渲染結(jié)果僅由 props.item.id
決定,則上述是一個很好的實現(xiàn)。但是,如果具有相同 id 的 item 可能會隨時間而變化,或者如果渲染結(jié)果依賴于其他 prop,則需要修改 serverCacheKey
的實現(xiàn),以考慮其他變量。
返回常量將導(dǎo)致組件始終被緩存,這對純靜態(tài)組件是有好處的。
如果 renderer 在組件渲染過程中進行緩存命中,那么它將直接重新使用整個子樹的緩存結(jié)果。這意味著在以下情況,你不應(yīng)該緩存組件:
上下文
產(chǎn)生副作用(side effect)的子組件。
因此,應(yīng)該小心使用組件緩存來解決性能瓶頸。在大多數(shù)情況下,你不應(yīng)該也不需要緩存單一實例組件。適用于緩存的最常見類型的組件,是在大的 v-for
列表中重復(fù)出現(xiàn)的組件。由于這些組件通常由數(shù)據(jù)庫集合(database collection)中的對象驅(qū)動,它們可以使用簡單的緩存策略:使用其唯一 id,再加上最后更新的時間戳,來生成其緩存鍵(cache key):
serverCacheKey: props => props.item.id + '::' + props.item.last_updated
更多建議: