【Nuxtjs】431- 簡述Nuxt.js
- 2019 年 12 月 12 日
- 筆記
作者 | 孔令濤
Nuxt.js 是一個基於 Vue.js 的通用應用框架,一個用於Vue.js 開發SSR應用的一站式解決方案。它的優點是將原來幾個配置文件要完成的內容,都整合在了一個nuxt.config.js,封裝與擴展性完美的契合。
簡單說nuxtjs項目,它其實就是一個vue的項目融合一個node.js server項目,這裡node服務有兩個作用,第一點是代替瀏覽器的工作,籠統理解就是在created時的請求數據和頁面渲染,第二點是當作靜態文件伺服器,把渲染好的頁面返回給用戶。
ssr服務做快取的意義

在上圖中,我們可以看到一個簡單的ssr服務渲染流程,在這裡筆者把與前端渲染不同之處標紅,一個是初始化的數據。第二個是獲取數據後伺服器對於頁面的渲染。
圖中如果未使用快取,就會導致每一個用戶的對頁面的請求,都使用服務去渲染一次,這對於伺服器簡直是災難。特別是渲染所依賴的node.js服務,不論是express還是koa又或者是像nuxt的封裝,都繞不開渲染時對於伺服器cpu產生壓力。反之,使用快取,用記憶體空間換取cpu的使用率這是划算的,且屬於node.js的長項。
快取的使用思路
nuxt快取有三種,從小到大就是介面快取、組件快取、頁面快取,下面我們找具體的場景來聊一下。
1.介面快取,我們來看下下面這張圖。

這轉轉有書的首頁,你所能看到的都是從介面獲取的數據渲染的,往往首頁的數據的在一段時間內是不會變動的,也許是1小時、也許是幾天,我們每次都去服務端取數據,完全沒必要,所有介面做快取,在這種場景非常有必要。即便是頁面數據經常變動,通過一次請求,使用快取,代替用戶的n次請求對於api伺服器來說會有很不錯的收益。
2.組件快取

沒找到特別貼合的頁面,這裡就畫圖了,如上圖,你的組件會在多個服務端渲染的頁面中出現,使用組件快取是非常不錯的選擇。

再說一個極端都例子,例如一個頁面中是如上圖中的A、B組件的結構,A組件是長時間不會怎麼變且大量使用,B組件需要展示用戶頭像和用戶的名字,每個B組件渲染出來都不一樣,且這個頁面還要放在服務端渲染,那麼這樣的場景使用組件渲染是合適的。
上面這個極端的例子,千萬不要被誤導,因為B組件沒有可復用的地方,完全可以放在客戶端去渲染。
3.頁面快取 頁面快取的場景就是一個頁面長的一樣的部分,大量被用戶請求,那麼就可以做頁面快取,例如上面的首頁,在一段時間內,用戶看到的內容是不會變的。
這三種快取是包含關係,也就觸發了大級別的快取,就不會觸發小級別的快取,簡單來說就是一個請求找到頁面快取,肯定不需要再去請求介面了。
最後筆者選定是介面快取與頁面快取搭配使用,理由是我可以把那些類似於根據用戶不同而不同的推薦組件放到客戶端去獲取數據並渲染,也就是公共部分用服務端渲染,差異部分用客戶端渲染。這是對於我們現在的業務是最好的選擇。
快取的實踐
筆者在里並沒有使用常規的lru-cache這個包做快取,而是把介面與頁面的快取都做在里redis里。先說怎麼做,下面的思考部分我們再來聊筆者的理由。
下面是實現,先來說說介面快取:1.如何介面獲取的數據存入redis 在nuxt.config.js中,我們在modules配置中加入@nuxtjs/axios,這是nuxtjs自帶的,然後編寫一個叫axios.server.js的文件,加入plugins配置中,這裡的重點是文件命中一定要加server的標示,這樣nuxt在載入這個插件的時候只會把它載入到服務端去。

程式碼如上圖,比較好理解就是onResponse監聽一下介面返回的數據存入redis,這是存快取的部分。
axios獲取快取的程式碼如下。

注意點:這個一定要加上服務端的判斷,雖然打包的時候asyncData里的程式碼不會被打包到客戶端,但是在打包和開發的時候不加上服務端的判斷,會報一些無法引包的錯誤。這裡可以對axios進行封裝,但一定要注意服務端和客戶端。
2.頁面快取存入redis 這裡就比較簡單了,在nuxt.config.js中,serverMiddleware配置里加入一個中間件,程式碼如下。

在上面的中間件中你需要自己處理下哪些是你需要快取的,包括html、js、css。
問題
聊聊筆者為什麼想用redis代替lru-catch的方案,理由是使用redis,使我會擔心記憶體膨脹太快帶來的問題,而且多台負載的ssr服務可以共同使用一個快取,我們甚至可以通過操作redis主動的去管理快取,對於很多頁面、介面需要做快取來說,這樣做是很不錯的。
這樣一來,我們的ssr服務通過做快取解決里cpu使用率的問題,然後又通過使用redis解決了本地記憶體膨脹的問題,ssr服務變的更專心於io。
還有個問題就是快取的生存時間,例如我們設置了一個很長的快取的生存時間,介面的數據都變了,可是我們還在使用快取,當然你可以選擇一個合適長短的過去時間,可以從redis裡面把快取刪掉,這也是我們用redis存儲快取的好處。
還有就是要注意快取級別的問題,大級別的快取會覆蓋小級別的快取,例如客戶端一直在走頁面的快取,那麼介面快取怎麼刷新也沒用,這就需要我們做一些快取的關聯管理。思路如下圖。
