当前位置: 首页 > 科技观察

Vite如何使用Esbuild提升性能?

时间:2023-03-17 22:56:33 科技观察

前言在上一篇。为什么有人说vite快,有人说vite慢?在[1]中,我们提到在开发模式下使用Vite会带来降低首屏性能的负面影响。首屏性能下降的原因,一方面是因为devserver需要先完成pre-build,才能响应首屏请求;另一方面,它需要实时转换请求文件。可能有同学会问,是不是可以通过这两方面的优化来提升首屏的性能呢?原则上这样做是没有问题的,Vite也是如此。为了提升性能,Vite另辟蹊径,借助Esbuild的能力,快速完成项目打包和文件转换,进行预构建和内容转换,效果非常好。今天,我将通过这篇文章与大家分享Vite如何使用Esbuild提升性能。本文目录结构如下:Esbuild初探[2]什么是Esbuild[3]KeyAPI\-transform\&build[4]plugin[5]Esbuild在Vite中的巧妙使用[6]Pre-build[7]ContentsinmiddlewaresConversion[8]Conclusion初识Esbuild首先小编给大家简单介绍一下Esbuild。它的官方地址是:**Esbuild[9]**。什么是EsbuildEsbuild是一款基于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&buildEsbuild并不复杂。它提供了两个API——transform和build,使用起来非常简单。transfrom,转换的意思。通过这个api,我们可以将ts、jsx、tsx等格式的内容转成js。transform只负责文件内容转换,不会生成新文件。Build是指根据指定的单个或多个条目进行构建、分析依赖关系,并使用loader将不同格式的内容转换为js内容,生成一个或多个bundle文件。这两个API的使用方法:constres=awaitesbuild.transform(code,options)//将代码转换成指定格式的内容esbuild.build(options)//packandbuildcopycode关于使用transform,build需要要传入的具体配置项本文不再赘述。官网对这部分有很详细的说明。有兴趣的同学可以去官网-simple-options[11],Advancedoptions[12]看看,也可以自己动手试试。插件和Webpack、Rollup等构建工具一样,Esbuild也提供插件对外使用,让我们可以介入构建打包过程。这里要说明一下,plugins只能配置buildAPI的入参,不能transform。标准插件的标准格式如下:letcustomerPlugin={name:'xxx',setup:(build)=>{build.onResolve({filter:'',namespace:''},args=>{..});build.onLoad({filter:'',namespace:''},args=>{...});build.onStart(()=>{...});build.onEnd((结果)=>{...});}}复制代码其中setup可以帮助我们在build的各个过程中注册hooks。Esbuild提供的钩子比较简单。一共有4个钩子:onResolve,在解析url的时候触发。您可以自定义url的解析方式。如果回调返回路径,则不会执行后续相同类型的回调。所有onResolve回调将按照相应插件注册的顺序执行。onLoad,模块加载时触发,可以自定义模块的加载方式。如果回调返回内容,则不会执行后续相同类型的回调。所有onLoad回调将按照相应插件注册的顺序执行。onStart,每次构建开始时触发,没有入参,所以不具备改变构建的能力。多个插件的onStart是并行执行的。onEnd,每次构建结束都会触发,入参为构建结果,可以修改结果。所有的onEnds都会按照相应插件注册的先后顺序执行。正是有了onResolve、onLoad、onStart、onEnd,我们才可以在构建过程中的解析url、加载模块内容、构建开始、构建结束阶段进行干预,进行自定义操作。Esbuild在Vite中的巧妙运用了解了Esbuild的基本用法后,我就带大家看看Vite是如何使用Esbuild进行预构建和内容转换的。预构建首先,让我们回顾一下为什么要进行预构建。原因有二:将非ESM规范代码转换成ESM规范代码;将第三方依赖中的多个文件合并为一个,以减少http请求的数量;要完成预构建,最关键的两点是找到项目合并并转换所有第三方依赖和第三方依赖。在Esbuild的帮助下,Vite轻松实现了这两个需求。寻找第三方依赖寻找第三方依赖的过程很简单,分为两步:和Webpack、Rollup、Parcel等构建工具一样,Esbuild在做packagebuild的时候也会构建一个moduledependencygraph-modulegraph(详见为什么有人说vite快,有人说vite慢?-Webpack在快速冷启动中构建模块图[13]。构建模块图时,第一步是解析模块的绝对路径,此时会触发onResolvehook,当onResolvehook触发时,会传入模块的路径,根据模块的路径,我们可以判断模块是否是第三方-方依赖或业务代码,举个例子