VueSSR高階指南

嗨 各位小夥伴好,很久沒有寫文章了,此次分享一下咱們從使用node以來,前端架構上的一些優化 若是看過我上一篇文章B站的前端之路的小夥伴可能知道 咱們從去年開始打烊 使用node 到如今已經經歷了一年的迭代,承載的訪問量也從百萬級別 擴大到了如今的億級別,此次補充一些乾貨吧~css

vue如何實現熱更新

咱們都知道,對於node來講,前端vue代碼的迭代節奏是很快的,可能一週要迭代幾回,可是node的迭代卻沒那麼平凡,可能一週更新一次甚至更久,那麼爲了node服務的穩定,減小node服務的發佈次數,是很是有用的。 配置中心是確定須要的,由於須要經過配置不一樣的資源版本號,來通知node服務更新服務上的版本號 那麼 咱們的vue代碼 要如何改造才能實現熱更新呢? 咱們就以vue官方給的例子來看
如下代碼是我截取的兩段代碼官方案例:
首先他定義了一個createRenderer的方法
裏面調用的是vue-ssr的createBundleRender方法來建立的渲染函數
html

而後傳入了使用了三個文件,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),用來作開發時候的熱加載。 而後經過不一樣的啓動腳本,來配置上不一樣的環境變量參數,以此來啓動不一樣的頁面開發,這樣子,開發就方便多了,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-->是服務端渲染的佔位符) vue

而後,咱們看一下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的一些黑科技~

嗶哩嗶哩 乾杯~

相關文章
相關標籤/搜索