ssr源代码(SSR和前端编译在这点上是一样的)
ssr源代码(SSR和前端编译在这点上是一样的)
2024-11-06 05:17:29  作者:俄式爷们儿  网址:https://m.xinb2b.cn/life/irc335781.html

我们通过组件的方式来开发前端页面,在浏览器里面,组件渲染时会通过 dom api 对 dom 做增删改来显示相应的内容但在服务端并没有 dom api,我们可以把组件渲染成 html 字符串,然后下发到浏览器渲染,因为已经有了 html 了,就可以直接渲染成 dom,不再需要执行 JS,所以很快,接下来我们就来聊聊关于ssr源代码?以下内容大家不妨参考一二希望能帮到您!


ssr源代码

我们通过组件的方式来开发前端页面,在浏览器里面,组件渲染时会通过 dom api 对 dom 做增删改来显示相应的内容。但在服务端并没有 dom api,我们可以把组件渲染成 html 字符串,然后下发到浏览器渲染,因为已经有了 html 了,就可以直接渲染成 dom,不再需要执行 JS,所以很快。

第一种浏览器渲染的方式叫做 CSR (client side render),第二种服务端渲染的方式叫做 SSR(server side render)。

很明显,SSR 渲染出画面的速度会很快,因为不需要执行 JS ,而是直接解析 html。因此,app 里嵌的页面基本都用 SSR,这样体验会更好。而且低端机执行 JS 是可能很慢的,要是 CSR,那页面可能会有很长一段白屏时间。

此外,SSR 是直接返回了 html,这样搜索引擎的爬虫就能从中抓取到具体的内容,就会给更高的搜索权重,也就是更有利于 SEO (search engine optimize)。

在 app 里嵌的页面、搜索引擎排名优化这两种场景下,我们都要做 SSR。

知道了 SSR 是什么和为什么要做 SSR,那如何实现 SSR 呢?

SSR 实现原理

我们知道 vue 是通过 template 描述页面结构,而 react 是通过 jsx,但不管是 template 还是 jsx,编译后都会产生 render function,然后执行产生 vdom。

vdom 在浏览器里会通过 dom api 增删改 dom 来完成 CSR,在服务端会通过拼接字符串来完成 SSR。

图片

vdom 是一个树形结构,那么 SSR 就是遍历这棵树,拼接字符串的过程。

图片

看到这张图,不知你有没有想起编译的 generate 阶段也是这样的拼接字符串的过程:

图片

没错,SSR 中 vdom 打印成字符串,和编译中 AST 打印成字符串的逻辑确实是一样的。

口说无凭,我们来看下两者的源码再下结论。

Vue SSR 的渲染流程

vue 提供了 vue-server-renderer 这个包用于 SSR,它的作用就是把 Vue 组件渲染成字符串。

它提供了 createBundleRenderer 的 api:

const bundle = fs.readFileSync(resolve('./dist/server-bundle.js'), 'utf-8');

createBundleRenderer(bundle)

这个 bundle 就是 webpack 编译产生的目标代码:

图片

可能你会问,为啥要等 webpack 把代码编译成 bundle 才去渲染啊?

因为像 esm 的模块语法、像 ts、sass 等语法都不是 node 支持的呀,要先把代码编译打包成 bundle,这样才能在 node 里面跑。

这也是为啥提供的 api 叫做 createBundleRenderer。

创建好 renderer 之后,调用 renderToStream 方法,就开始执行渲染了。

当然,也可以调用 renderToString,这俩 api 的区别是一个是边渲染边返回内容,一个是完全渲染完再返回内容。

图片

渲染第一步,自然是要把传入的 bundle 给执行了:

图片

这里 runInVm 就是执行 bundle 那段字符串的代码,这是基于 node 提供的 vm 包的 api 实现的:

图片

通过 vm.runInContext 可以在某个上下文中执行一段代码。

执行之后,返回的就是 Vue 的实例:

图片

注意,这里是在 node 环境里创建的 Vue 实例,所以没有 dom api,不能操作 dom,但可以打印成字符串:

图片

这里 render 的实现就是拼接字符串:

图片

这样遍历完一遍 vdom,就拼接好了最终的 html:

图片

把这段 html 返回给浏览器即可。这样我们就实现了 Vue 的 SSR!

小结一下 Vue SSR 的流程:

vue-server-renderer 包提供了 createBundleRenderer 的 api,可以传入编译打包后的 bundle 代码来创建一个 renderer。renderer 有 renderToString 和 renderToStream 的 api。内部会通过 vm.runInContext 来执行 bundle 的代码,产生 Vue 实例,之后把 Vue 实例的 vdom 渲染成 html 字符串。返回这个 html 字符串就实现了 SSR。

当然,实际做 SSR 的时候,我们不会直接用 vue-server-renderer,而是会用封装了一层的 nuxt.js,因为它对路由等做了处理,并且对工具链的封装也很好,开箱即用。

到了这里,我们可以说 SSR 就是遍历 vdom 拼接字符串的过程了。

接下来再看下编译中的 generate 阶段:

编译流程

前端领域的编译基本都是源码转源码,所以流程都差不多,都是 parse、transform、generate 这三步:

图片

parse 阶段把源码转为 AST(抽象语法树),然后 transform 阶段会对 AST 做各种增删改,generate 阶段会把修改后的 AST 递归打印成字符串。

这里的 generate 阶段就像 SSR 的 render 一样,也是个拼接字符串的过程:

比如 babel 的 generate 的实现是这样的:

打印 while 节点:

图片

打印 condition 节点:

图片

递归遍历 AST,打印每个节点,拼接字符串,就能产生目标代码。

所以说,SSR 的 vdom render 和前端编译的 AST generate 是一样的逻辑,都是拼接字符串。

当然,也是有很多不同的地方的,比如 SSR 的 vdom 是动态执行 render function 产生的,而编译中的 AST 是从源码中静态编译产生的。只是代码生成的拼接字符串的逻辑一样。

总结

SSR 渲染首屏画面速度快,而且利于搜索引擎的抓取,所以在 app 里嵌的页面、SEO 这两种场景下,我们都会做 SSR。

SSR 的原理就是把 vdom 打印成 字符串,这和前端编译中的 generate 阶段很类似。

我们看了 Vue 的 vue-server-render 包的源码,它提供了 createBundleRenderer 的 api,传入编译打包后的 bundle 代码,通过 vm 执行它,然后把产生的 Vue 实例的 vdom 打印成 html 字符串,就实现了 SSR。

我们也看了 babel generator 的源码,它提供了每种节点的打印逻辑,递归遍历 AST,拼接字符串,就能产生目标代码。

虽然 SSR 和前端编译在流程上和目的上都不同,但是在生成代码这一点上是一样的,都是把树形结构打印成字符串。

  • 被仲裁的公司怎么消除影响(小公司不怕仲裁只能认倒霉)
  • 2024-11-06小公司不怕仲裁只能认倒霉以我历史上参加过20场仲裁开庭的经验告诉你,和小公司的纠纷,找劳动监察比仲裁有效得多!首先,我们必须得承认这样一个现实:小公司还真不怎么怕仲裁因为他们没有上市、融资的计划,也不在乎声誉信誉再加上仲裁一。
  • 最健康的9件小事(关注健康每一天)
  • 2024-11-06关注健康每一天【健康提醒】寒冷不会导致关节炎,但会加重疼痛寒冷不会直接导致关节炎,受凉后会出现关节疼又是什么原因?江苏疾控中心表示,针对这一现象在科学上还没有肯定的解释,有研究表示,一方面关节软组织受到寒冷刺激,敏。
  • 古代扬州瘦马(古人腰缠十万贯)
  • 2024-11-06古人腰缠十万贯南朝时期,有几个人在一起谈论人生理想一人说:“我要当扬州太守”一人说:“我要拥有很多钱财”一人说:“我要骑鹤上天成仙”最后一人说:“腰缠十万贯,骑鹤上扬州”显而易见,最后想把做官、发财、成仙三者一并拥。
  • 周扬青为什么要原谅罗志祥(凌晨5点罗志祥再向周扬青道歉)
  • 2024-11-06凌晨5点罗志祥再向周扬青道歉昨天闹了一天的周扬青爆料罗志祥事件,热度太高了,实实在在地霸占了热搜榜第一的位置而之前一贯以阳光形象在公众面前出现的罗志祥,一天之内变成了让人觉得不可思议的渣男关键是周扬清的爆料太猛,让人猝不及防周扬。
  • 沈从文的忆湘西过年全书概括(沈从文笔下的边城人)
  • 2024-11-06沈从文笔下的边城人“溪流如弓背,山路如弓弦”这里是文学巨匠沈从文笔下的边城,历史上曾位于湘、黔、川的交界处,素有“一脚踏三省”之称(在三省市交界处的边城)在这个地方的年夜餐桌上,有一道菜,叫“一锅煮三省”,据说能将湘、。
  • 喝茶一般都是用的什么杯子(各种材质的饮水杯)
  • 2024-11-06各种材质的饮水杯在前几年泡茶喝茶还经常会被打上“中年人”的标签,但如今爱上喝茶泡茶的年轻人越来越多,大家对于喝茶这件事的仪式感也越来越强从茶叶的挑选到茶具的搭配都大有学问,今天要来说一说的就是关于喝茶的杯子,到底什么。
  • 煮茴香菜怎么做(煮茴香菜的做法)
  • 2024-11-06煮茴香菜的做法首先把茴香菜摘好,放入清水里洗干净,然后切成十厘米左右的长度沥干水备用焯水是想把怀香菜里面干涩的味道,把它抄掉,然后打回香菜控,水捞出然后上锅放入一定量的清水,然后放入几片姜片,放入怀香菜,把它煮开,。
  • 各高铁春运客流 多因叠加客流骤增
  • 2024-11-06各高铁春运客流 多因叠加客流骤增河南日报客户端记者代娟通讯员常昊三六九,往外走1月27日,正月初六,春节假期最后一天,高铁新乡东站迎来返程高峰,从预售车票信息来看,当日预计发送旅客1.4万人次该站当日办理站停列车148列,打破建站1。
  • 1.6t车型哪款值得入手(1.5T1.6L2.0T值得买的6款车)
  • 2024-11-061.5T1.6L2.0T值得买的6款车在我们日常家庭用车的考量中,动力是不少车主都比较在意的一个点,而1.5T、1.6L、2.0T几乎是市面上消费者购买最多的3种,今天就让我们来看一下在这三种排量的发动机中值得买的6款车1.5T:长安CS。
  • 展信佳 见字如晤是什么意思
  • 2024-11-06展信佳 见字如晤是什么意思展信佳,是一种问候语也可以说是祝福语,祝察看这封信的你一切安好的意思见字如晤是中国早期(明代开始)使用的一种表达方式,字面意思是见到这些字就好像当面见到人一样,多用于写信时如对长辈,就是您见到这封信就。
  • 李思思春晚口误(李思思晒春晚后台花絮)
  • 2024-11-06李思思晒春晚后台花絮伴随着倒计时敲响,大家迎来了新的一年,而在春晚舞台上全程陪同大家跨年的央视主持李思思,在社交平台上发布了一则春晚后台花絮视频视频中李思思、撒贝宁、尼格买提、任鲁豫以及首登春晚舞台的马凡舒齐齐出镜,因为。