背景
在ssr的頁面中經(jīng)常需要根據(jù)數(shù)據(jù)生成頁面的情況,這種時候如果服務(wù)端可以將數(shù)據(jù)緩存起來就可以直接生成頁面,減少首屏加載時間。
基本流程
對于不需要及時更新的數(shù)據(jù)舔痕,可以將請求的結(jié)果在服務(wù)端進行緩存幾分鐘,在過期前使用緩存的數(shù)據(jù)豹缀,過期后再重新請求接口伯复,而不需要每次客戶端的頁面請求都向接口服務(wù)器獲取相同的數(shù)據(jù)。
結(jié)合需求考慮邢笙,在訪問量不大啸如、緩存數(shù)據(jù)較少的情況下,不使用redis氮惯,直接使用內(nèi)存存儲數(shù)據(jù)组底。減少開發(fā)工作。
要點
Nuxt
根據(jù)需求筐骇,代碼應(yīng)在服務(wù)端進行頁面構(gòu)建前判斷是否存在緩存與數(shù)據(jù)請求,而nuxt提供了Router Middleware
路由中間件江滨。
Router Middleware
可以在頁面顯示前執(zhí)行函數(shù)铛纬,其中首次訪問的頁面渲染是在服務(wù)端進行的,后面通過前端路由跳轉(zhuǎn)的函數(shù)有客戶端執(zhí)行唬滑。所以在執(zhí)行邏輯前需要判斷process.server
確保當前的運行環(huán)境告唆。
Router Middleware
還提供了頁面context作為函數(shù)傳參,其中包含了vuex的store實例晶密,通過store就可以將數(shù)據(jù)傳遞給客戶端擒悬。
lru-cache
lru-cache是一個用于緩存的js庫,通過這個庫稻艰,我們可以實現(xiàn)設(shè)置數(shù)據(jù)新鮮度與大小限制懂牧,對于短時間內(nèi)的并發(fā)請求,還會進行合并成一個請求。
實踐
// @/utils/cache.js
const LRUCache = require('lru-cache')
const { getList } = require('./get-list')
function createCache() {
const cache = new LRUCache({
max: 500, // 大小限制
ttl: 1000 * 60 * 2, // 過期時間
fetchMethod: getList // 請求接口函數(shù)僧凤,通過promise返回值
})
return cache
}
module.exports = { createCache }
// @/middleware/initData.js
import { createCache } from "@/utils/cache"
const cache = createCache()
export default async function({ store }) {
// // 只在服務(wù)器初始化獲取blog列表
if (process.server) {
const list = await cache.fetch('list')
store.commit('setList', list)
}
}
// @/nuxt.config.js
module.exports = {
...
router: {
middleware: ['initData']
},
...
}
注意
在本地通過NODE_ENV=development
啟動服務(wù)時畜侦,可能出現(xiàn)緩存無效的問題,這是因為在開發(fā)環(huán)境下躯保,中間件函數(shù)不以單例模式運行旋膳,每次請求都會重新初始化lru-cache。但在生產(chǎn)環(huán)境不存在這個問題途事。
如果想要開發(fā)環(huán)境也統(tǒng)一使用緩存可以通過module自定義模塊验懊,在應(yīng)用構(gòu)建時創(chuàng)建lru-cache實例,再利用addServerMiddleware
方法尸变,創(chuàng)建一個接口用于獲取緩存义图。路由中間件修改成從這個接口中獲取數(shù)據(jù)。