前端打包工具webpack、vite、rollup的区别及使用
- webpack、vite、rollup的区别
- webpack、vite的区别
- 为什么vite比webpack打包快?
- 为什么有人会说vite慢?
- 首屏问题
- 懒加载问题
- 解决方案
- 注意点
- webpack
- webpack打包过程
- webpack打包原理
- 第一次冷启动慢的原因
- 热更新慢的原因
- vite
- vite开发环境打包
- vite生产环境打包
- 生产环境的构建为什么使用 esbuild,而选择 rollup ?
- esbuild语言
- rollup
webpack、vite、rollup的区别
Webpack 是功能最丰富的打包工具,适用于大型项目和复杂应用。
Rollup 专注于打包 JavaScript 库,生成优化的、轻量级的代码。
vite基于rollup实现了热更新也适合打包项目
webpack、vite的区别
webpack | vite |
---|---|
启动时各个模块之间的依赖,然后进行编译,打包后的代码在本地服务器渲染 | 启动时不需要分析各个模块之间的依赖关系、不需要打包编译。可按需动态编译缩减时间。当项目越复杂、模块越多的情况下,vite明显优于webpack。 |
热更新时,部分代码变更, 整个模块的代码都需要重新编译,然后在推送更新 | 当改动了某个模块的时候,也只用让浏览器重新请求该模块 |
基于nodejs构建,js是以毫秒计数。 | 基于esbulid预构建依赖,esbulid是采用go语言编写的,go语言是纳秒级别的 |
Vite采用了ES模块来实现模块的加载。目前基于web标准的ES模块已经覆盖了超过90%的浏览器。 | |
webpack生态相对丰富 | vite相关生态没有webpack完善,vite可以作为开发的辅助。 |
为什么vite比webpack打包快?
- 因为它在启动的时候不需要打包,即不用分析模块与模块之间的依赖关系,也不用进行编译。这种方式就类似于UI组件按需加载。当浏览器请求某个模块时,vite对其按需动态编译.
- 热更新方面,效率更高。当改动了某个模块的时候,也只用让浏览器重新请求该模块,不需要像webpack那样将模块以及模块依赖的模块全部编译一次。
为什么有人会说vite慢?
Vite 的快,主要体现在两个方面: 快速的冷启动和快速的热更新,即上一节解释;
而他的慢呢?请看一下:
首屏问题
某个界面是首次进入,且依赖比较多/比较复杂的话,那就会比较慢了。
vite启动快的原理,也导致了他在加载依赖项很多,很复杂的页面时,页面打开慢。因为他把 dev server 启动过程中完成的工作,转移到了 dev server 响应浏览器请求的过程中,不可避免的导致首屏性能下降。
由于 unbundle 机制,首屏期间需要额外做以下工作:
- 不对源文件做合并捆绑操作,导致大量的 http 请求;
- dev server 运行期间对源文件做 resolve、load、transform、parse 操作;
- 预构建、二次预构建操作也会阻塞首屏请求,直到预构建完成为止;
不过首屏性能差只发生在 dev server 启动以后第一次加载页面时发生。之后再 reload 页面时,首屏性能会好很多。原因是 devserver 会将之前已经完成转换的内容缓存起来。
懒加载问题
- 由于 unbundle 机制,动态加载的文件,需要做 resolve、load、transform、parse 操作,并且还有大量的 http 请求,导致懒加载性能也受到影响。
- 如果懒加载过程中,发生了二次预构建,页面会 reload,对开发体验也有一定程度的影响。
解决方案
1.如果项目首屏过于卡顿,不妨看看这篇文章-vite性能优化 — 增加业务代码预构建,加快首屏输出
2.官网也有部分解释-VITE官网:依赖优化选项
3.也可以参考下面这种方案
插件使用,万能的开发者开发的插件,让我们谢谢他!
npm i -D vite-plugin-optimize-persist vite-plugin-package-config
// vite.config.ts
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
export default {
plugins: [
PkgConfig(),
OptimizationPersist()
]
}
package.json 会自动生成其依赖项,当然你也可以手动加,但不建议,因为很多呀~
注意点
- 首次加载的时候,依然会很慢,这个是正常现象,因为这个插件第一次也没法知道,哪些依赖需要预构建,他只是在vite动态引入资源的时候,将这些资源都记录下来,自动写入了package.json中,当再次启动项目的时候,插件会读取之前他写入在package.json中的数据,并告知vite,这样vite就能对这些资源进行预构建了。
- 如果在这之后,被人再拿到你的源代码,因为package.json中已经有了预构建配置了,所以,他的vite在第一次启动时,就能对资源进行预构建了,另外,如果你由于某些原因需要删除node_modules/.vite这个缓存目录, 由于有这个插件,你的这次首次渲染也会快起来。
webpack
webpack打包过程
1.识别入口文件
2.通过逐层识别模块依赖。(Commonjs、amd或者es6的import,webpack都会对其进行分析。来获取代码的依赖)
3.webpack做的就是分析代码。转换代码,编译代码,输出代码
4.最终形成打包后的代码
webpack打包原理
1.先逐级递归识别依赖,构建依赖图谱
2.将代码转化成AST抽象语法树
3.在AST阶段中去处理代码
4.把AST抽象语法树变成浏览器可以识别的代码, 然后输出
第一次冷启动慢的原因
在之前的浏览器中没有模块化的设计,所以期望把所有源代码编译进一个 js文件中提供给浏览器使用,所以在开发中当我们运行启动命令的时候,webpack 总是需要从入口文件去索引整个项目的文件,编译成一个或多个单独的js 文件,即使采用了代码拆分,也需要一次生成所有路由下的编译后文件(这也是为什么代码拆分对开发模式性能没有帮助)。这也导致了服务启动时间随着项目复杂度而指数增长。
热更新慢的原因
当基于打包器启动时,编辑文件后将重新构建文件本身。显然我们不应该重新构建整个包,因为这样更新速度会随着应用体积增长而直线下降。
而即使我们使用了HMR, 更新速度也会随着应用规模的增长而显著下降。
vite
vite开发环境打包
- Vite 一开始将应用中的模块区分为依赖和源码两类,
- vite在开发环境时,基于浏览器支持esm,让浏览器解析源码模块,然后服务器按需编译返回(浏览器的原生 ES Modules 能力允许在不将代码打包到一起的情况下运行 JavaScript 应用),基于esbuild进行预构建(开发环境)打包不常变动的第三方依赖包,并进行缓存。
- Vite 利用 HTTP 头来加速整个页面的重新加载,源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age,immutable 进行强缓存,因此一旦被缓存它们将不需要再次请求。
- 热更新时,当某个模块内容改变时,让浏览器去重新请求该模块即可,而不是像webpack重新将该模块的所有依赖重新编译,
vite生产环境打包
- 构建应用程序
- Rollup打包:Vite在生产环境中使用Rollup进行打包。将应用程序中的所有模块打包成一个或多个bundle文件,以便在生产环境中使用。
- 代码压缩和优化:Rollup可以对代码进行压缩和优化,例如删除未使用的代码、合并模块等,以减少最终生成的代码的大小。
- 生成最终的静态资源:在打包完成后,Vite会生成最终的静态资源文件,包括JavaScript文件、CSS文件和其他静态文件,这些文件可以直接部署到Web服务器上。
vite本身并不参与编译,它的编译能力只是集成了rollup和ESbuild的功能.
生产环境的构建为什么使用 esbuild,而选择 rollup ?
这是因为 esbuild 在代码分隔、css 处理等方面的功能仍在开发中,rollup 在应用打包方面更加的成熟且灵活
esbuild语言
- 使用 Go 编写,并且编译成了机器码
- 大量使用并行算法
- esbuild 的所有内容都是从零编写的,避免了不要的数据转换
- 更有效利用内存
rollup
Rollup是一个现代化的JavaScript模块打包器,专注于打包JavaScript库和应用程序。它采用了ES模块的标准,并支持各种JavaScript模块格式,包括ES modules、CommonJS、AMD等。通过插件和工具的组合来处理Vue文件的各个部分(模板、样式、脚本),将它们转换为浏览器可识别的格式,并最终生成最小化、优化的打包文件。
- rollup基于esm打包,打包生成的文件更小。Rollup不支持HMR(识别commonJs需要插件)
-基于rollup- npm发包教程 react组件–npm发包总过程-基于rollup