1. 热模块替换(Hot Module Replacement, HMR)
首先,让我们聊聊热模块替换(HMR)。简单来说,当你修改了一个文件,比如一个组件或者一个函数,然后保存,这时候你希望浏览器里的应用能够自动更新显示最新的变化,而不是每次都得手动刷新页面。这个功能就叫 HMR。
Webpack 的 HMR 实现方式是这样的:当某个模块发生变化时,Webpack 会尝试只更新这个模块,而不会重新加载整个页面。但是有时候这个过程并不完美,尤其是对于复杂的依赖关系,可能会导致整个页面都需要重新加载。
Vite 则使用了一种更现代的方法来实现 HMR。它基于原生的 ES Modules 动态导入特性 (import()) 来实现。这意味着当一个模块发生变化时,Vite 可以非常精确地知道哪些部分需要更新,哪些不需要,从而只更新真正改变了的部分。这种方式更加高效,几乎感觉不到延迟。
2. 开发服务器启动时间
再来谈谈开发服务器启动的时间。当你第一次启动项目时,开发服务器需要做很多工作,比如解析所有的模块依赖,生成中间代码等。这一步骤对于大型项目来说可能会花费不少时间。
Webpack
在启动时会进行一个完整的构建过程,包括预解析所有模块的依赖关系。这样做虽然有助于生产环境下的优化,但是在开发环境中会导致启动时间变长。特别是对于一些依赖文件很多或是关系复杂的大型项目,webpack的这种“不构建完不给看”的死脑筋做法会导致启动时间变得相当长。
Vite
则采用了不同的策略。它不会一开始就构建整个项目,而是采用按需编译的方式。也就是说,只有当浏览器请求某个文件时,Vite 才会去编译这个文件。
sayHello.js:
export default function sayHello() { console.log('hello world'); }
main.html:
<script type="module"> import hello from './sayHello.js'; sayHello(); // hello world </scirpt>
就拿上面这段代码来说,浏览器(当然得是支持ES module的浏览器)在执行到 import hello from './sayHello.js';
之前甚至都不知道还有这么个东西存在,只有到这一行才会去发送请求。这样一来,开发服务器可以在很短的时间内启动起来,等到你开始浏览项目的时候,Vite 就会一边加载一边编译文件,用户体验非常好。
为了各位看官老爷能够更加清晰理解这一点,就举个很现实的例子。各位去下馆子的时候,要是后厨为了上菜好看,或者是餐桌上真就有一个这么扫兴的人,必须等菜都上齐了之后拍完照才能吃的话,想必各位都得暗暗不爽,但要是上一道吃一道,对于我这种吃货来说无疑是极好的,而这也就是webpack和vite的区别。
3. 网络的并发请求
据不可靠消息,webpack在开发之处就试图去像如今的vite一样做成按需引入的效果,但苦于当时还处于http1时代,单个域名并发请求撑死也就是六七个,再多的话就会造成阻塞的问题,所以不得不去减少打包后的产物从而避免http的阻塞。但是随着不断的发展完善,现如今的http2已经没有了当年的并发限制,所以这也是vite利用rollup去把打包产物分为多个小模块的前提条件。
4. 开发过程
除了刚刚提到的那些技术方面的差异,开发人员对于开发过程也有影响,以前页面简单,折腾来折腾去无非就是css,html,图片之类的文件。但是还明显现在已经不止于这些东西了,音频,gif动画,ts语言,图片压缩等各式各样的文件甚至是3D模型都往上面放,而webpack又得依靠不同的loader去把它们解析成js模块。这就好比西餐切鱼,切肉,切菜,切水果都得用不同的刀,而中餐则是一把带蒜味的菜刀就足以砍遍菜市场。于是这就造成webpack不得不频繁切换使用各类loader,而vite则是更倾向打造更加“锋利且多功能的中式菜刀”
5. 构建优化
最后,我们来看看构建优化方面的一些差异。
Webpack 是一个非常强大的工具,在上一篇文章中我用“菜刀和锅”的例子去给各位提到了webpack中的plugin以及loader,在它们的帮助下,webpack可以像切菜炒菜一样处理各种类型的资源,比如 CSS、JavaScript、图片等等。但是这种灵活性也带来了配置的复杂性,有时候可能会导致较大的输出文件和较长的构建时间。也就是说无论是“刀钝了”还是“锅漏了”,甚至是只要一个地方由于文件过大或是其他杂七杂八的原因卡住了,都会导致整个项目的构建速度大大下降。
不仅如此,webpack是基于node去运行的,虽说现在node在处理多任务的时候并不会比Java,c等多线程语言慢太多,但js作为单线程语言依旧是无法很好的利用到CPU的多核优势,所以构建速度也会相应的变慢。
Vite 在生产构建时使用了 Rollup,这是一个专门为现代 JavaScript 应用设计的打包工具。Rollup 非常擅长处理 ES Modules,并且能够生成更小的文件大小和更快的构建速度。Vite 结合了 Rollup 的优势,使得最终的打包结果既快速又轻量。
并且不同于webpack基于js的运行方式,vite无论是预构建还是按需编译的过程都是通过go语言编写的esbuild去运行的,多线程语言能够充分发挥CPU的多核优势,从而大幅度提升速度。
总结
综上所述,Vite 之所以能够在打包速度上胜过 Webpack,主要是因为它采用了更现代的技术栈,比如 ES Modules 的动态导入,以及更高效的 HMR 实现。此外,Vite 在开发服务器启动时采用的按需编译策略,以及生产构建时使用 Rollup 进行优化,这些因素共同作用使得 Vite 成为了一个非常快速的开发工具。希望本文能帮助你更好地理解 Vite 与 Webpack 在打包速度上的差异,并根据项目需求选择合适的构建工具。最后祝各位读者姥爷0 waring(s),0 error(s)。