前言

谈到 Vite,给人的第一印象便是 dev server 发动速度快。相同规划的项目,比较 Webpack 动辄十几秒乃至几十秒的的发动速度,Vite 几乎是快到没朋友,往往数秒之内即可完结发动(PS: 都没有时刻去喝一杯 ☕️ 啦)。

正好小编最近在做一些关于开发体会的功用优化,就想着把手上一些项目的开发形式更新为 Vite。经过一番操作,终于改造成功,而作用也不负众望,项目发动速度由本来的 25 s 如坐 一般跃升为 2 s,几乎夸大。虽然也出现了一些比方首屏、懒加载功用下降等负面作用,但全体来说仍然利大于弊,开发幸福感提高十分明显。

接下来小编就经过本文给咱们剖析一下,详细聊一聊 Vite 的快和慢。

本文的目录结构如下:

  • Vite 的快

    • 快速的冷发动

    • 快速的热更新

  • Vite 的慢

    • 首屏功用

    • 懒加载功用

  • 结束语

Vite 的快

Vite 的快,首要体现在两个方面: 快速的冷发动和快速的热更新。而 Vite 之所以能有如此优异的体现,彻底归功于 Vite 借助了浏览器ESM 规范的支撑,采取了与 Webpack 彻底不同的 unbundle 机制。

在本章节,小编将经过一个实际的项目,别离运用 WebpackVite 发动 dev server, 给咱们展现一下 Vite 的威力。

快速的冷发动

因为是公司的内部项目,不方便将源代码上传到 github,所以小编只能经过 gif 动图的方法给咱们展现 WebpackVite 发动 dev server 的进程。

  • Webpack

    首先是经过 Webpack 发动 dev server,进程如下:

    一个规划不是很大的项目,dev server 发动完结,竟然花了 25 s 左右时刻。假如项目持续迭代变得再大一点,那每次发动 dev server 便是一种折磨了。

    这个问题,首要是由 Webpack 内部的中心机制 – bundle 形式引发的。

    Webpack 能大行其道,归功于它划时代的采用了 bundle 机制。经过这种 bundle 机制,Webpack 能够将项目中各种类型的源文件转化供浏览器识别的 jscssimg 等文件,树立源文件之间的依靠联系,并将数量巨大的源文件合并为少数的几个输出文件。

    bundle 作业机制的中心部分分为两块:构建模块依靠图 – module graph 和将 module graph 分化为终究供浏览器运用的几个输出文件。

    构建 module graph 的进程能够简单概括为:

    1. 获取配置文件中 entry 对应的 url (这个 url 一般为相对路径);
    2. resolve – 将 url 解析为绝对路径,找到源文件在本地磁盘的方位,并构建一个 module 目标;
    3. load – 读取源文件的内容;
    4. transform – 运用对应的 loader 将源文件内容转化为浏览器可识别的类型;
    5. parse – 将转化后的源文件内容解析为 AST 目标,剖析 AST 目标,找到源文件中的静态依靠(import xxx from 'xxx') 和动态依靠(import('xx'))对应的 url, 并搜集到 module 目标中;
    6. 遍历第 5 步搜集到的静态依靠、动态依靠对应的 url,重复 26 进程,直到项目中所有的源文件都遍历完结。

    分化 module graph 的进程也能够简单概括为:

    1. 预处理 module graph,对 module graphtree shaking
    2. 遍历 module graph,根据静态、动态依靠联系,将 module graph 分化为 initial chunkasync chunks
    3. 优化 initial chunkasync chunks 中重复的 module
    4. 根据 optimization.splitChunks 进行优化,别离第三方依靠、被多个 chunk 共享的 modulecommon chunks 中;
    5. 根据 chunk 类型,获取对应的 template
    6. 遍历每个 chunk 中搜集的 module,结合 template,为每个 chunk 构建最终的输出内容;
    7. 将最终的构建内容输出到 output 指定方位;

    Webpack 的这种 bundle 机制,奠定了现代静态打包器(如 RollupParcelEsbuild)的规范作业形式。

    但是成也萧何败萧何,强壮的 bundle 机制,也引发了构建速度缓慢的问题,并且项目规划越大,构建速度越是缓慢。其首要原因是构建 module graph 的进程中,涉及到很多的文件 IO、文件 transfrom、文件 parse 操作;以及分化 module graph 的进程中,需求遍历 module graph、文件 transform、文件 IO 等。这些操作,往往需求消耗很多的时刻,导致构建速度变得缓慢。

    开发形式下,dev server 需求 Webpack 完结整个作业链路才能够发动成功,这就导致构建进程耗时越久,dev server 发动越久。

    为了加快构建速度,Webpack 也做了很多的优化,如 loader缓存功用、webpack5 的耐久化缓存等,但这些都治标不治本,只需 Webpack 的中心作业机制不变,那 dev server 发动优化,依旧是一个负重致远的进程(基本上永远都达不到 Vite 那样的作用)。

  • Vite

    相同的项目,这次换 Vite 发动。

    经过 gif 动图,咱们能够看到 dev server 的发动速度仅仅需求 2s 左右,比较 Webpack 如 匍匐相同的速度,就如同坐 一般,开发幸福感登时拉满。

    Vite 之所以在 dev server 发动方面,如此给力,是因为它采取了与 Webpack 截然不同的 unbundle 机制。

    unbundle 机制,望文生义,不需求做 bundle 操作,即不需求构建、分化 module graph,源文件之间的依靠联系彻底经过浏览器对 ESM 规范的支撑来解析。这就使得 dev server 在发动进程中只需做一些初始化的作业,剩余的彻底由浏览器支撑。这和 Webpackbundle 机制一比,几乎便是降维冲击,都有点欺负人了 。

    那有的同学就会问,源文件的 resolveloadtransformparse 什么时分做呢 ?

    答案是浏览器发起恳求今后,dev server 端会经过 middlewares 对恳求做阻拦,然后对源文件做 resolveloadtransformparse 操作,然后再将转化今后的内容发送给浏览器。

    这样,经过 unbundle 机制, Vite 便能够在 dev server 发动方面获取远超于 Webpack 的优异体会。

    最终再总结一下, unbundle 机制的中心:

    • 模块之间的依靠联系的解析由浏览器实现;
    • 文件的转化由 dev servermiddlewares 实现并做缓存;
    • 不对源文件做合并绑缚操作;

快速的热更新

除了 dev server 发动外, Vite 在热更新方面也有十分优异的体现。

咱们仍是经过同一个项目,对 WebpackVite 的热更新做一下比较。

  • Webpack

    首先是 Webpack 在热更新方面的体现。

    调查 gif 动图,修正源文件今后,Webpack 发生耗时大概 5 s 的从头编译打包进程。

    dev server 发动今后,会 watch 源文件的变化。当源文件发生变化后,Webpack 会从头编译打包。这个时分,因为咱们只修正了一个文件,因而只需求对这个源文件做 resolveloadtransfromparse 操作,依靠的文件直接运用缓存,因而 dev server 的响应速度比冷发动要好很多。

    dev server 从头编译打包今后,会经过 ws 连接通知浏览器去获取新的打包文件,然后对页面做部分更新。

  • Vite

    再来看看 Vite 在热更新方面的体现。

    调查 gif 动图,能够发现 Vite 在热更新方面也是碾压 Webpack

    因为 Vite 采用 unbundle 机制,所以 dev server 在监听到文件发生变化今后,只需求经过 ws 连接通知浏览器去从头加载变化的文件,剩余的作业就交给浏览器去做了。(忍不住要给 Vite 点个 了。)

综上, Vitedev server 冷发动和热更新方面,对 Webpack 的优势实在是太明显了,难怪会遭到咱们的青睐。

Vite 的慢

bundle 机制有利有弊相同,unbundle 机制给 Vitedev server 方面取得巨大功用提高的一起,也带来一些负面影响,那便是首屏懒加载功用的下降。

在本章节,小编仍是经过相同的项目为咱们一一展现。

首屏功用

咱们先来比照一下 WebpackVite 在首屏方面的体现。

  • Webpack

    Webpack 的首屏 gif 动图如下:

    浏览器向 dev server 发起恳求, dev server 接遭到恳求,然后将现已打包构建好的首屏内容发送给浏览器。整个进程十分遍及,没有什么可说的,不存在什么功用问题。

  • Vite

    比较 WebpackVite 在首屏方面的体现就有些差了。

    经过 gif 动图,咱们能够很明显的看到首屏需求较长的时刻才能彻底显现。

    因为 unbundle 机制,首屏期间需求额定做以下作业:

    • 不对源文件做合并绑缚操作,导致很多的 http 恳求;
    • dev server 运转期间对源文件做 resolveloadtransformparse 操作;
    • 预构建、二次预构建操作也会堵塞首屏恳求,直到预构建完结为止;

    Webpack 比照,Vite 把需求在 dev server 发动进程中完结的作业,转移到了 dev server 响应浏览器恳求的进程中,不行避免的导致首屏功用下降。

    不过首屏功用差只发生在 dev server 发动今后第一次加载页面时发生。之后再 reload 页面时,首屏功用会好很多。原因是 dev server 会将之前现已完结转化的内容缓存起来。

懒加载功用

  • Webpack

    在懒加载方面, Webpack 的体现也正常,没什么好说的。

    为什么有人说 vite 快,有人却说 vite 慢?

  • Vite

    相同的, Vite 在懒加载方面的功用也比 Webpack 差。

    和首屏相同,因为 unbundle 机制,动态加载的文件,需求做 resolveloadtransformparse 操作,并且还有很多的 http 恳求,导致懒加载功用也遭到影响。

    此外,假如懒加载进程中,发生了二次预构建,页面会 reload,对开发体会也有一定程度的影响。

结束语

尽管在首屏、懒加载功用方面存在一些缺乏,但瑕不掩瑜,作为现在最 的构建东西,Vite 能够说是实至名归。并且这些问题并非不行处理,比方咱们能够经过 prefetch耐久化缓存等手法做优化,信任 Vite 未来也会做出对应的改善。

总的来说, Vite 仍是未来可期的,还没有开始运用的小伙伴,能够去测验一下噢,。