Vue3 与 vite 的效率提升的原因

506 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

Vue3 与 vite 的效率提升的原因

讨论该问题时,我们可以将其拆分成两道经典的面试题:vue3 的效率提升的主要表现有哪几方面谈谈 vite 的原理及其与 webpack 的区别

1.vue3 的效率提升的主要表现有哪几方面?

官方说:vue3客户端渲染效率比 vue2 提升了 1.3 ~ 2 倍,SSR 渲染效率比 vue2 提升了 2 ~ 3 倍。

效率提升的主要表现有以下五方面有:

  1. 静态提升

静态内容(静态节点、静态属性)会被提升,vue3中静态节点不会被编译成虚拟节点,只会被编译成一个静态字符串,从而提升了 diff 算法的对比效率。

  1. 预字符串化

当编译器遇到大量(20 个)连续的静态节点时,会直接将其编译为一个普通字符串节点,而只有动态节点编译成虚拟节点。

<div class="menu-bar-container">
  <div class="logo">
    <h1>logo</h1>
  </div>
  <ul class="nav">
    <li><a href="">menu</a></li>
    <li><a href="">menu</a></li>
    <li><a href="">menu</a></li>
    <li><a href="">menu</a></li>
    <li><a href="">menu</a></li>
  </ul>
  <div class="user">
    <span>{{ user.name }}</span>
  </div>
</div>

当编译器遇到大量连续的静态内容,会直接将其编译为一个普通字符串节点

const _hoisted_2 = _createStaticVNode(
  '<div class="logo"><h1>logo</h1></div><ul class="nav"><li><a href="">menu</a></li><li><a href="">menu</a></li><li><a href="">menu</a></li><li><a href="">menu</a></li><li><a href="">menu</a></li></ul>'
);

vue2 与 vue3 虚拟节点树对比: image-20200929170205828image-20200929170304873

  1. 缓存事件处理函数

事件处理函数会被缓存起来,保证事件处理函数只生成一次。

<button @click="count++">plus</button>
<script>
// vue2
render(ctx){
  return createVNode("button", {
    onClick: function($event){
      ctx.count++;
    }
  })
}

// vue3 cache为缓存函数
render(ctx, _cache){
  return createVNode("button", {
    onClick: cache[0] || (cache[0] = ($event) => (ctx.count++))
  })
}
</script>
  1. Block Tree

    • vue2 在对比新旧树的时候,并不知道哪些节点是静态的,哪些是动态的,因此只能一层一层比较,这就浪费了大部分时间在比对静态节点上。
    • 而 vue3 会将根节点(具有动态后代节点)设为 Block 节点,在该根节点创建一个数组记录其后代节点中的动态节点,对比时不在逐层对比,而是只对比 Block 节点。

vue2 与 vue3 对比: image-20200929172002761 image-20200929172555681

  1. PatchFlag
    • vue2 在对比每一个节点时,并不知道这个节点哪些相关信息会发生变化,因此只能将所有信息依次比对,
    • 而 vue3 会对动态节点的动态内容进行标记。如: text - 表示内容变化、class - 表示类名变化。
<div class="user" data-id="1" title="user name">{{user.name}}</div>
image-20200929172805674

2.谈谈 vite 的原理及其与 webpack 的区别?

vite 的主要优势是开发过程中 vite 启动速度比 webpack 快很多;模块化标准方面 webpack 使用 CommonJS 规范,vite 使用了官方的 ES Module 规范;打包到生产环境时,vite 使用传统的 rollup 进行打包。

2.1 效率提高的主要原因

  • 因为 webpack 使用 CommonJS 规范,而浏览器本身是不支持该规范的;所以初次启动时 webpack 会将所有模块进行打包合并,分析每个模块的依赖并进行编译,该过程会消耗一定的时间,因此 webpack 启动速度较慢。

  • 而 vite 使用官方的 ES Module 规范,并且现代浏览器本身就支持 ES Module;因此可以将开发环境下的模块文件直接作为浏览器要执行的文件,而不用像 webpack 那样先进行打包合并,编译过程中浏览器会自动向依赖的 Module 发送请求。所以 vite 就可采用按需动态编译的方式,当浏览器请求某个模块时,再根据需要对模块内容进行编译,从而极大的缩减了启动时间。

  • 因此工程项目越复杂、模块越多,vite 的优势就越明显。

2.2 效率提高的主要表现

  1. 打包过程方面
  • webpack 会先将所有模块进行打包,然后再启动开发服务器,我们请求某个模块就直接给予该模块打包后的结果;

  • 而 vite 不进行打包合并就直接启动开发服务器,当我们请求某个模块时再对该模块进行实时编译,编译完成后返回其结果,因此 vite 启动更快。

webpack 原理图: image-20200929144416064

vite 原理图: image-20200929144957808

  1. Hot Module Replacement(HMR)方面

    当我们改动了一个模块后,webpack 需要把依赖该模块的所有模块都重新编译一次,而 vite 仅需让浏览器重新请求该模块并重新编译即可 ,因此 vite 的 HMR 效率更高。

结语

这是我目前所了解的知识面中最好的解答,当然也有可能存在一定的误区。

所以如果对本文存在疑惑,可以在评论区留言,我会及时回复的,欢迎大家指出文中的错误观点。

最后码字不易,觉得有帮助的朋友点赞、收藏、关注走一波。