寫過Vue SSR的都知道,Vue經過提供server和client的webpack插件生成bundle josn,從而實現相似服務端的熱更以及客戶端資源的優化注入。那麼這兩個個bundle到底有什麼神奇的呢?OK,話很少說,進入正題css
首先看看客戶端的json,明顯看到,裏面藉助webpack插件,把spa用到的文件進行了分類,publicPath
是公共路徑,all 是全部的文件,initial
是入口文件依賴的js和css,async
是首屏不須要的異步的js,分析這些出來有什麼用呢,主要是用來優化生成的html的資源注入,這個在後面會講到 html
而後咱們再康康服務端生成的json,entry
是服務款入口的文件,files
是服務端依賴的文件列表,maps
是sourcemaps文件列表,這裏暫時是空 前端
帶着這個問題,我去看了一下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-map
npm庫,在堆棧出錯的時候,把錯誤的文件和函數進去,經過消費sourcemap來還原定位源文件的具體的位置和行數 能夠說,腦洞真的很大,但這就完了嗎,不止~webpack
前面咱們只講了服務端的json,那客戶端也生成了一份呢,那個有什麼用呢?咱們再次進入vue源碼去挖掘,🤡很快就找到了答案web
但這裏有個維度,哪些是入口文件,哪些是異步文件,vue服務端自帶client-plugin已經幫咱們抽離出來了,OK,回到咱們構建html,對於入口文件和css,咱們會作preload的優化,對於異步的會作prefetch優化,同時對於入口的js還會作個script標籤的defer加載提升併發數npm
Vue SSR就是這麼巧妙地利用兩個webpack插件提取項目的關鍵信息生成bundle,從而達到服務器熱更以及前端加載優化,真的能夠說腦洞很大json