淺談Vue SSR中的Bundle

前言

寫過Vue SSR的都知道,Vue經過提供server和client的webpack插件生成bundle josn,從而實現相似服務端的熱更以及客戶端資源的優化注入。那麼這兩個個bundle到底有什麼神奇的呢?OK,話很少說,進入正題css

客戶端 vue-ssr-client-manifest.json

首先看看客戶端的json,明顯看到,裏面藉助webpack插件,把spa用到的文件進行了分類,publicPath是公共路徑,all 是全部的文件,initial是入口文件依賴的js和css,async是首屏不須要的異步的js,分析這些出來有什麼用呢,主要是用來優化生成的html的資源注入,這個在後面會講到 html

服務端 vue-ssr-server-bundle.json

而後咱們再康康服務端生成的json,entry是服務款入口的文件,files是服務端依賴的文件列表,maps是sourcemaps文件列表,這裏暫時是空 前端

若是把files展開,會看到裏面是一堆文件列表,文件名跟key同樣,而後value裏面,對的,你沒看錯,是一段js,裏面就是服務端渲染須要的代碼,那道理我都懂,爲何有這段就能夠實現服務端代碼的熱更以及sourcemap的定位呢

服務端的熱更和sourcemap

帶着這個問題,我去看了一下vue服務端的源碼,左邊框的三個文件就是實現這些神奇效果的關鍵之處了,其中右邊框的entry、files就是咱們上面服務端對應的jsonvue

接下來咱們再去看看createBundleRunner裏面這個方法,最關鍵是evaluateModule 裏面調用getCompiledScript這個方法,其中evaluateModule 還會把執行的結果緩存到evaluatedFiles裏面去

getCompiledScript裏面經過調用vm.Scirpt把咱們在entry裏面的代碼丟進vm建立的沙箱裏面,同時也是要compiledScripts把生成的script片斷緩存起來

vm.Script建立沙箱,咱們還能夠傳入sandbox上下文,若是entry建立的沙箱依賴其餘文件,還能夠遞歸建立沙箱,經過這樣作,咱們就能夠監聽服務端文件變化的時候建立新的服務端json,再建立新的沙箱來執行,從而達到nodejs熱更的效果

其中咱們知道runInNewContext決定是否建立新的上下文,咱們知道若是設置爲false,則會使用runInThisContext建立沙箱,可是會容易污染全局global,若是咱們使用runInNexContext來建立,同時傳入咱們預先傳入的sandbox,就能夠隔離上下文,可是這樣有個壞處,就是建立新的上下文會有必定的資源消耗,node

若是咱們使用once來建立,就不會每一個請求都建立新的隔離上下文,而是建立一個新的隔離上下文公用,這樣就能夠最大限度避免V8建立的消耗,能夠看到,只有在沒有runner的狀況下才纔會建立sandbox

至於sourcemap,經過使用mozilla這個source-mapnpm庫,在堆棧出錯的時候,把錯誤的文件和函數進去,經過消費sourcemap來還原定位源文件的具體的位置和行數 能夠說,腦洞真的很大,但這就完了嗎,不止~webpack

前面咱們只講了服務端的json,那客戶端也生成了一份呢,那個有什麼用呢?咱們再次進入vue源碼去挖掘,🤡很快就找到了答案web

客戶端的注入優化

咱們知道服務端渲染會返回一個html,而後接下來客戶端會走一次hydration,客戶端須要的文件,例如js和css,咱們須要在寫在html裏面,而後經過http去請求文件回來,否則怎麼hydration啊

但這裏有個維度,哪些是入口文件,哪些是異步文件,vue服務端自帶client-plugin已經幫咱們抽離出來了,OK,回到咱們構建html,對於入口文件和css,咱們會作preload的優化,對於異步的會作prefetch優化,同時對於入口的js還會作個script標籤的defer加載提升併發數npm

總結

Vue SSR就是這麼巧妙地利用兩個webpack插件提取項目的關鍵信息生成bundle,從而達到服務器熱更以及前端加載優化,真的能夠說腦洞很大json

相關文章
相關標籤/搜索