前言
小伙伴们在面试的时候,是否有碰到过这样的问题,面试官:说说你对前端构建工具的理解 ?这时候大家就可能会说出自己比较熟悉的两个构建工具了, Webpack 和 Vite, 然后开始介绍他们两个之间的差异。面试官之后问出Vite为什么这么快?那么对这两个构建工具底层原理不太明白的小伙伴们,可能就不知道该怎么回答了,今天我们就来聊聊Vite为什么这么快!
那么要提到Vite为什么这么快, 我们就不得不先说Webpack了。因为通常我们是会拿他们两个的速度来进行比较。
在上篇文章中我们介绍了前端为什么需要构建工具以及Webpack的作用,感兴趣的小伙伴们可以看看:聊聊构建工具Webpack
Webpack
模块化是在我们前端中十分重要的一个概念,当我们的项目体量很大时,模块化就起到了一个十分重要的作用。它可以帮助我们更方便地去维护我们的代码。就比如我们经常使用的ES Modules模块化,它本身是存在着浏览器的环境兼容问题的。尽管现在市面上的主流浏览器都支持ESM模块化,但是在以前还是有许多浏览器用不了的。
所以Webpack就诞生了,因为浏览器在执行我们的代码时,它本身是没有一个很好的办法去读懂我们文件中的引入关系的,例如import、require等。
底层原理
Webpack启动之后,首先会查看我们项目中的一个Webpack配置项,通常是Webpack.config, 找到我们项目中的一个入口文件(通常是一个js文件)。然后通过这个js文件中使用到的import、require等引用语句, 找到该文件所依赖的资源模块。然后每个依赖的资源模块中也可能会有所依赖的资源模块,层层递归下去,最后得出一个整个项目的依赖关系树。
而Webpack拿到了对应的依赖关系树后,使用对应的loader去解析每个文件,例如css-loader,可以将scss和less文件转成css文件,bable可以将es5+ → es5,读到整个项目的文件代码,放到出口文件中,从而实现整个项目的打包,交给浏览器执行。
所以我们最后就得到了一个打包文件,它里面包含着所有具有引用关系的代码,最后浏览器只用执行该文件就可以了,完美的解决了浏览器没有一个很好的方式去读懂模块化文件的问题!
缺点
虽然Webpack通过这种递归的方式,去解决了浏览器无法读懂模块化的问题,但是这种方法也带来了一个副作用。
在项目体量过于大时,Webpack 在处理递归模块依赖时可能会遇到构建速度缓慢的问题。这种情况通常发生在项目中存在大量相互依赖的文件或模块时。递归依赖增加了 Webpack 分析和打包的复杂性,从而导致构建时间的增加。
Vite为什么这么快?
随着网络技术飞速发展,浏览器也在迅速的进步。它已经可以渐渐的读懂模块化的代码了。浏览器会将import
语句处理成一个http
请求,去获取import
引入的各种模块.
Vite就是借助浏览器可以读懂模块化代码这一特性,不用将入口文件层层递归的去处理成一个文件执行,而是借助将项目中的各种文件处理成一个网络请求,当浏览器执行到了模块依赖的代码,就自动的去请求对应的代码资源。
1. 基于 ES Modules 的原生支持
Vite 利用现代浏览器对 ES Modules 的原生支持,在开发环境中不需要像 Webpack 那样进行文件的预打包或转换。Vite 会使用浏览器的原生能力来解析模块,并只在浏览器请求时进行模块加载。这种按需加载机制极大地减少了初次启动时间。
2. 按需编译
在开发模式下,Vite 使用的是按需编译策略。当你访问某个页面时,只编译并提供该页面及其直接依赖的模块,而不是整个应用。这避免了不必要的工作,使得启动和热更新速度非常快。
但是Vite如果是在生产阶段下,还是会使用到一个叫rollup
的构建工具,将文件进行打包成一个出口文件,因为拥有着大量的用户的情况下,如果依然使用着这种请求的方式,那么对服务器会造成很大的负担。