浅谈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

相关文章
相关标签/搜索