前面我们有提到Vite在开发阶段,提倡的是一个no-bundle的理念,不必与webpack那样需要先将整个项目进行打包构建。但是no-bundle的理念只适合源代码部分(我们自己写的代码),vite会将项目中的所有模块分为依赖与源码两部分。
依赖:指的是一些不会变动的一些模块,如:node_modules中的第三方依赖,这部分代码vite会在启动本地服务之前使用esbuild进行预构建。esbuild 使用 Go 编写,比使用 JavaScript 编写的打包器预构建依赖快 10-100 倍。
源码:指的是我们自己开发时写的那部分代码,这部分代码可能会经常变动,并且一般不会同时加载所有源代码。
所以总结来说:no-bundle是针对源码的,而预构建是针对第三方依赖的
主要有以下两点:
比如React,它就没有ESM的版本,所以在使用Vite时需要预构建
图片
比如常用的loads-es
我们引入lodash-es工具包中的debounce方法,此时它理想状态应该是只发出一个请求
import { debounce } from 'lodash-es'
事实也是这样:
图片
但这是预构建的功劳,如果我们对lodash-es关闭预构建呢?
vite配置文件加上如下代码,再来试试:
// vite.config.jsoptimizeDeps: { exclude: ['lodash-es'] }
图片
可以看到,此时发起了600多个请求,这是因为lodash-es 有超过 600 个内置模块!
vite通过将 lodash-es 预构建成单个模块,只需要发起一个HTTP请求!可以很大程度地提高加载性能
由于Vite的预构建是基于性能优异的Esbuild来完成的,所以并不会造成明显的打包性能问题
一般来说,Vite帮我们默认开启了预构建
图片
预构建产物会存放在:node_modules/.vite/deps
图片
里面会有一个_metadata.json的文件,这里保存着已经预构建过的依赖信息
对于预构建产物的请求,Vite会设置为强缓存,有效时间为1年,对于有效期内的请求,会直接使用缓存内容
图片
如果只有HTTP强缓存肯定也不行,如果用户更新了依赖版本,在缓存过期之前,浏览器拿到的一直是旧版本的内容。
所以Vite对本地文件也设置了缓存判断,如果下面几个地方任意一个地方有变动,Vite将会对依赖进行重新预构建:
图片
图片
图片
默认情况下,Vite会抓取项目中的index.html来检测需要预构建的依赖
optimizeDeps: { entries: ['index.html']}
如果指定了 build.rollupOptions.input,Vite 将转而去抓取这些入口点。
排除需要预构建的依赖项
optimizeDeps: { exclude: ['lodash-es']}
默认情况下,不在 node_modules 中的依赖不会被预构建。使用此选项可强制选择预构建的依赖项。
optimizeDeps: { include: ['lodash-es']}
还是从源码入手,在启动服务的过程中会执行一个initDepsOptimizer表示初始化依赖优化
图片
接着找到定义initDepsOptimizer方法的地方
图片
在这里会执行createDepsOptimizer方法,再接着找到定义createDepsOptimizer的地方
图片
这里首先会去执行loadCachedDepOptimizationMetadata用于获取本地缓存中的metadata数据
图片
该函数会在获取到_metadata.json文件内容之后去对比lock文件hash以及配置文件optimizeDeps内容,如果一样说明预构建缓存没有任何改变,无需重新预构建,直接使用上次预构建缓存即可。
如果没有缓存时则需要进行依赖扫描:
图片
这里主要是会调用scanImport方法,从名字也能看出该方法应该是通过扫描项目中的import语句来得到需要预编译的依赖
图片
最终会返回一个prepareEsbuildScanner方法:
图片
最后该方法中会使用esbuild对扫描出来的依赖项进行预编译。
本文链接:http://www.28at.com/showinfo-26-97753-0.html深入了解Vite:依赖预构建原理
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com