1. 程式人生 > 程式設計 >Nuxt頁面級快取的實現

Nuxt頁面級快取的實現

雖然 Vue 的伺服器端渲染 (SSR) 相當快速,但是由於需要為每次請求為了避免交叉請求狀態汙染,都建立一個新的根Vue例項,建立元件例項和虛擬 DOM 節點的開銷,無法與純基於字串拼接的模板的效能相當。在 SSR 效能至關重要的情況下,明智地利用快取策略,可以極大改善響應時間並減少伺服器負載。同時還可以大大減少後端介面伺服器的負載。

在 vue SSR指南 中,快取有兩種,分為頁面級快取和元件級快取。本次講的是頁面快取,如果內容不是使用者特定的並且在相對較短時間內,頁面內容不需要更新。我們就可以使用頁面快取。對於頁面級快取我們可以通過這段koa伺服器的程式碼大概知道快取的思路:

const microCache = LRU({
 max: 100,maxAge: 1000 // 重要提示:條目在 1 秒後過期。
})

const isCacheable = req => {
 // 實現邏輯為,檢查請求是否是使用者特定(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)
 }
 })
})

流程圖如下:

Nuxt頁面級快取的實現

上面的程式碼為vue的ssr渲染提供了方案,但是對於使用nuxt框架的同學而言,用腳手架初始化完,框架對於vue服務端渲染的res.end()函式做了高度封裝,從下圖nuxt在接收到請求後進行渲染的流程可以看出,nuxt主要是通過nuxtMiddleware呼叫renderRoute()來進行渲染的:

Nuxt頁面級快取的實現

那麼我們是否可以通過重寫renderRoute()這個api攔截其內部渲染邏輯,在渲染之前加上快取呢? nuxt-ssr-cache 外掛已經這樣做了。我們來看一下這個nuxt模組核心部分的原始碼:

const renderer = nuxt.renderer;
const renderRoute = renderer.renderRoute.bind(renderer);
renderer.renderRoute = function(route,context) {
 // hopefully cache reset is finished up to this point.
 tryStoreVersion(cache,currentVersion);

 const cacheKey = (config.cache.key || defaultCacheKeyBuilder)(route,context);
 if (!cacheKey) return renderRoute(route,context);

 function renderSetCache(){
  return renderRoute(route,context)
   .then(function(result) {
    if (!result.error) {
     cache.setAsync(cacheKey,serialize(result));
    }
    return result;
   });
 }

 return cache.getAsync(cacheKey)
  .then(function (cachedResult) {
   if (cachedResult) {
    return deserialize(cachedResult);
   }

   return renderSetCache();
  })
  .catch(renderSetCache);
};

在這段程式碼中,先儲存了renderer原來的renderRoute程式碼,之後又重寫了renderRoute程式碼,返回了一個通過cache快取來獲取快取內容的邏輯。cache返回了一個promise,如果是resolve的,並且有快取的內容,就直接返回快取內容。如果沒有快取內容或者reject,就執行renderSetCache()。而renderSetCache()中,返回了原來最初的renderRoute()處理邏輯,同樣如果renderRoute()返回的promise被resolve了,那麼就通過cache的setAsync方法來進行快取,之後返回渲染結果。

使用方法大家自行參考git中的readme文件,這裡就不說了。

下面我們真正來模擬一下,看看這個模組的功效到底如何。我們通過ab命令

ab -n 4000 -c 50 -s 120 -r http://localhost:3000/

來進行壓測:

第一種情況,沒有新增頁面快取,大約持續請求了10秒鐘,執行到3600個請求的時候,發生錯誤,不再繼續請求了:

Nuxt頁面級快取的實現

我們來通過日誌看下是什麼錯誤:

Nuxt頁面級快取的實現

可以看到FATAL ERROR這一句,JavaScript heap out of memory。堆記憶體已經沒有辦法再進行分配,所以程序終止了。

我們在終止之前通過程序監視器可以看到node程序已經彪到了1.7GB的記憶體。

Nuxt頁面級快取的實現

第二種情況,我們添加了頁面快取,通過server端的日誌,我們可以看出,只請求了一次後端的api資料介面,說明快取已經成功攔截了頁面請求。請求資料如下:

Nuxt頁面級快取的實現

在2秒鐘之內,就順利結束了4000個請求,記憶體沒有任何明顯波動,優化效果顯而易見。

到此這篇關於Nuxt頁面級快取的實現的文章就介紹到這了,更多相關Nuxt 頁面級快取內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!