vuessr高階指南

vuessr高階指南

37 人贊了文章

嗨 各位小夥伴好,好久沒有寫文章了,這次分享一下我們從使用node以來,前端架構上的一些優化

如果看過我上一篇文章[B站的前端之路](B站的前端之路 - 掘金)的小夥伴可能知道 我們從去年開始打烊 使用node 到現在已經經歷了一年的迭代,承載的訪問量也從百萬級別 擴大到了現在的億級別,這次補充一些乾貨吧~

vue如何實現熱更新

我們都知道,對於node來說,前端vue代碼的迭代節奏是很快的,可能一周要迭代幾次,但是node的迭代卻沒那麼平凡,可能一周更新一次甚至更久,那麼為了node服務的穩定,減少node服務的發布次數,是非常有用的。

配置中心是肯定需要的,因為需要通過配置不同的資源版本號,來通知node服務更新服務上的版本號

那麼 我們的vue代碼 要如何改造才能實現熱更新呢?

我們就以vue官方給的例子來看

以下代碼是我截取的兩段代碼[官方案例](github.com/vuejs/vue-ha):

首先他定義了一個createRenderer的方法, 裡面調用的是vue-ssr的createBundleRender方法來創建的渲染函數

然後傳入了使用了三個文件,template.html bundle.json 和clientmanifest.json

這裡可以看到 在createRender的時候 傳入的clientMainfest bundle 都是reqire的

那麼有同學會想,我要支持熱更新 是不是根據require的緩存機制,去定時的清理緩存?雖然也能實現但是其實不用的

我查詢了官方的api文檔,其實bundle支持三種參數

然後再看下vue的源碼,如果傳入的是一個絕對路徑,類似於上面這個案例 require某個dist目錄下的bundle.json文件的時候 做了什麼處理

它判斷 如果是一個js 或者json文件路徑的 那麼 他會先讀取這個文件,然後通過json轉化一下成對象,然後再走下面的判斷是否是oject邏輯

那麼,我們不是可以替他做這個事情嘛

我們可以從遠程讀取到bundle文件 然後將他轉化成bundle 然後傳入給createBundleRender方法 就可以不用通過require方法去獲取了

然後遠程bundle文件加上版本號,就可以實現通過配置來熱更新

vue項目與node項目分離

為了前後端分離,我們在前端和api層中間,架構了一層node層,用來做服務端渲染,來加快用戶的首屏可用和對搜索引擎的友好。項目一開始放置在同一個git倉庫裡面,分別放在client目錄和server目錄中(或者類似於vue 官方例子中的一樣,node服務可能只有一個sever.js。因為server中可能需要client中的一些資源,所以不得不將他們放在一起。後來通過配置中心驅動之後,client 和server 可以完全獨立,通過配置中心建立連接。所以完全可以將client項目和server項目分離開。

其實就是在前端項目中,再做了一次前後端分離,這次分離的原因 跟與api的前後端分離有些不一樣。這次是因為 第一個 前端vue項目本就是一個完全獨立的項目,拖著server項目反而顯的不是那麼靈活,同樣,server裡面包含了client,雖然可以獨立發布,但是因為迭代周期的不同,在管理分支上面總歸有點變扭,索性分開,各過各的

各過各的是極好的,可是開發的時候怎麼各過各的啊(f***~),我開發的時候要走服務端渲染的邏輯的啊,你讓我先基於客戶端開發,然後再配合著node調試一波?那可不是反而增加了開發成本

有沒有可以讓client獨立也能跑ssr的邏輯,然後最後只要跟正式的node服務通過配置中心配合起來就好了呢?

有啊,給client配置一個簡單的服務不就好了么?一般的nodessr不都是這樣的么 說白了就我上面說的,一個sever.js。裡面是一個基於koa的簡單服務,加上了koawepack的中間件[(koa-webpack)](Package - koa-webpack),用來做開發時候的熱載入。

然後通過不同的啟動腳本,來配置上不同的環境變數參數,以此來啟動不同的頁面開發,這樣子,開發就方便多了,npm run start:home 就是開發首頁,npm run start:video 就是開發播放頁 後面加上server參數就是開發服務端渲染 例如 npm run start:home:server

(這裡我只提供一個思路昂~具體實現要講的東西太多了,這裡不太想寫 >_>~~)

容災

既然是個node服務,那麼對於服務也要有相應的容災方案,不然怎麼放心將大流量交給它

那麼,我們需要一個降級方案以備不時之需(以下內容需要建立在你對vuessr有一定了解的基礎之上)

首先 vue 服務端渲染都有兩個入口文件,entryclient.js和entryserver.js 如果要支持降級,那麼需要在entryclient.js上面動一些手腳,我們仍然以官方例子為例

現在index.temlate.html 增加一個客戶端渲染容器,一個名為de-app的div(<!--vue-ssr-outlet-->是服務端渲染的佔位符)

然後,我們看一下entryclient.js裡面

這裡是用來同步服務端數據到客戶端store裡面的,那麼,如果降級到客戶端渲染,這裡就需要做一下兼容

我們默認服務端渲染一定會有window.__INITIAL_STATE__,如果沒有 說明服務端沒有幫我們取到數據,也就是降級到了客戶端渲染,那麼需要重新運行以下asyncData方法來從客戶端獲取一下數據,然後掛載到我們預先設定好的de-app上面,當然 原本掛載到app上的 也要做一下判斷了

這樣子,服務端如果沒有渲染出內容來,那麼,頁面還是可以通過客戶端渲染,重新走一遍邏輯,正常輸出頁面來。

vue代碼改完了,我們在構建的時候,也要以兩種目的去打包我們的html,一種是純粹的模版html(template.html),裡面除了一些固定的js引入外,沒有vue打包相關的js引入,是用來給服務端渲染當作模版用的(就是上面說的傳遞給createBundleRender的),另一個打包將構建好的js css引入進去了(degrage.html),可以直接當客戶端渲染的靜態模版使用 (就是使用兩次htmlwebpackplugin 一個傳chunks 一個不傳)

那麼具體怎麼使用這兩個文件呢?

我們準備了三層降級

* 1.首先 node服務上面,自己起了一個服務,用來監測所有的node進程的cpu使用率是否大於設定的閾值,如果超過設定閾值,那麼返回我們事先準備好的degrade.html文件,降級掉服務端渲染,可以大大減少服務端的渲染壓力,當然也可以手動設置是否需要降級嘛,來去自如

* 2.如果Node不幸 炸了,那麼 需要在slb 這一層上 也就是nginx 做一個配置,如果服務返回的code是5xx,那麼將流量指向我們實現發布好的degrade.html

* 3.如果非常不幸,全炸了,那麼如果頁面配置了cdn緩存,cdn回源失敗,就返回之前緩存上的頁面

那麼在極端情況下,其實還是會有首屏頁面展示給用戶的(數據兜底會讓這個方案更完美,下次有機會再補上吧)

這次就這麼多吧,下次可能會補充上一些別的優化和**react**的一些黑科技~

嗶哩嗶哩 乾杯~

推薦閱讀:

別人家的node都是100萬級別的,我的怎麼5000+伺服器就開始主動斷開連接了?
nodejs工程師一般工作內容是什麼?
零後端基礎想搭建一個高可用的node服務,需要學習什麼,有什麼比較好的教程或者開源練手項目么?
跟我學Nodejs(三)

TAG:Vuejs | Nodejs | 嗶哩嗶哩 |