Vite 是怎样利用 Esbuild 来提升性能的 ?

前言

在上一篇 为什么有人说 vite 快,样利用有人却说 vite 慢?提升[1] 中,我们提到过开发模式下使用 Vite 会有首屏性能下降的样利用负面效果。之所以会造成首屏性能下降,提升一方面是样利用 dev server 需要完成预构建才可以响应首屏请求;另一方面是需要对请求文件做实时转换。

也许有的提升同学会问,是样利用不是针对这两个方面做优化,就可以提升首屏性能呢?提升原则上这样是没有问题的,而且 Vite 也是样利用这么做的。为了能提升性能,提升Vite 另辟蹊径的样利用借助了 Esbuild 能快速完成项目打包、文件转换的提升能力来进行预构建、内容转换,样利用效果非常好。提升

今天小编就通过本文和大家一起聊一聊 Vite 是样利用怎样利用 Esbuild 来提升性能的。

本文的目录结构如下:

 初探 Esbuid[2]

 什么是 Esbuild[3]

 关键 API \- transform \& build[4]

 plugin[5]

 Esbuild 在 Vite 中的巧妙使用[6] 预构建[7]

 middlewares 中内容转换[8]

 结束语

初探 Esbuild

首先,小编先带大家简单了解一下 Esbuild,b2b信息网其官方地址是: **Esbuild[9]**。

什么是 Esbuild

Esbuild 是一款基于 Go 语言开发的 javascript 打包工具,最大的一个特征就是快。

通过官网提供的一张图,我们可以清晰的看到 Esbuild 的表现是多么优秀:

image.png

同样规模的项目,使用 Esbuild 可以将打包速度提升 10 - 100 倍,这对广大一直饱受 Webpack 缓慢打包速度折磨的开发人员来说,简直就是福音。

而 Esbuild 之所以能这么快,主要原因有两个:

 Go 语言开发,可以多线程打包,代码直接编译成机器码;

  Webpack 一直被人诟病构建速度慢,主要原因是在打包构建过程中,存在大量的 resolve、load、transform、parse 操作(详见 为什么有人说 vite 快,有人却说 vite 慢?- 快速的源码下载冷启动[10] ),而这些操作通常是通过 javascript 代码来执行的。要知道,javascript 并不是什么高效的语言,在执行过程中要先编译后执行,还是单线程并且不能利用多核 cpu 优势,和 Go 语言相比,效率很低。

 可充分利用多核 cpu 优势;

关键 API - transfrom & build

Esbuild 并不复杂。它对外提供了两个 API - transform 和 build,使用起来非常简单。

transfrom,转换的意思。通过这个 api,我们可以将 ts、jsx、tsx 等格式的内容转化为 js。transfrom 只负责文件内容转换,并不会生成一个新的文件。

build,构建的意思,根据指定的单个或者多个入口,分析依赖,高防服务器并使用 loader 将不同格式的内容转化为 js 内容,生成一个或多个 bundle 文件。

这两个 API 的使用方式:

const res = await esbuild.transform(code, options) // 将 code 转换为指定格式的内容

esbuild.build(options) // 打包构建

复制代码

关于使用 transform、build 需要传入的具体配置项,本文就不详细说明了,官网对这一块儿有很详细的说明,感兴趣的同学可以去官网 - simple-options[11]、Advanced options[12] 看看,也可以自己动手试试。

plugin

和 Webpack、Rollup 等构建工具一样,Esbuild 也提供了供外部使用的 plugin,使得我们可以介入构建打包过程。

 在这里要说明一点,只有 build 这个 API 的入参中可以配置 plugin,transform 不可以。

一个标准的 plugin 的标准格式如下:

let customerPlugin = {

name: xxx,

setup: (build) => {

build.onResolve({ filter: , namespace: }, args => { ...});

build.onLoad({ filter: , namespace: }, args => { ... });

build.onStart(() => { ... });

build.onEnd((result) => { ... });

}

}

复制代码

其中,setup 可以帮助我们在 build 的各个过程中注册 hook。

Esbuild 对外提供的 hook 比较简单,总共 4 个:

 onResolve, 解析 url 时触发,可自定义 url 如何解析。如果 callback 有返回 path,后面的同类型 callback 将不会执行。所有的 onResolve callback 将按照对应的 plugin 注册的顺序执行。

 onLoad, 加载模块时触发,可自定义模块如何加载。如果 callback 有返回 contents,后面的同类型 callback 将不会执行。所有的 onLoad callback 将按照对应的 plugin 注册的顺序执行。 onStart, 每次 build 开始时都会触发,没有入参,因此不具有改变 build 的能力。多个 plugin 的 onStart 并行执行。

 onEnd, 每次 build 结束时会触发,入参为 build 的结果,可对 result 做修改。所有的的 onEnd 将按照对应的 plugin 注册的顺序执行。

正是有了 onResolve、onLoad、onStart、onEnd,我们可以在 build 过程中的解析 url、加载模块内容、构建开始、构建结束阶段介入,做自定义操作。

Esbuild 在 Vite 中的巧妙使用

了解了 Esbuild 的基本用法以后,小编就带大家一起来看看 Vite 是怎么利用 Esbuild 来做预构建和内容转换的。

预构建

先来回顾一下为什么要做预构建。

原因有两点:

 将非 ESM 规范的代码转换为符合 ESM 规范的代码;

 将第三方依赖内部的多个文件合并为一个,减少 http 请求数量;

要完成预构建,最关键的两点是找到项目中所有的第三份依赖和对第三方依赖做合并、转换。借助 Esbuild,Vite 很轻松的实现了这两个诉求。

 寻找第三方依赖

寻找第三方依赖的过程非常简单,分为两步:

和 Webpack、Rollup、Parcel 等构建工具一样,Esbuild 在做打包构建时也要构建模块依赖图 - module graph(具体过程可参考 为什么有人说 vite 快,有人却说 vite 慢?- 快速的冷启动[13] 中 Webpack 构建 module graph)。

在构建 module graph 时,第一步就是解析模块的绝对路径,这个时候就会触发 onResolve hook。在 onResolve hook 触发时,会传入模块的路径。根据模块的路径,我们就可以判断出这个模块是第三方依赖还是业务代码。

   举个

IT科技类资讯
上一篇:使用U盘安装XP系统的步骤和注意事项(详细教程分享,轻松安装旧版本Windows系统)
下一篇:如何以3分钟强制删除管理员权限文件(快速、高效、安全的解决办法)