Vite是什么?为什么比webpack快?

vite 是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:

  • 一个基于浏览器原生 ES Module 的轻量 dev server。
  • 一套生产构建指令(默认使用 Rollup)。

其作用类似 webpack + webpack-dev-server,特点如下:vite 会直接启动开发服务器,不需要进行打包操作,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快;利用现代浏览器支持 ES Module 的特性,当浏览器请求某个模块的时候,再根据需要对模块的内容进行编译,这种方式大大缩短了编译时间。

使用 vite 时,从 vite 命令启动,到最后的页面展示,需要经历的过程:

  • 使用 esbuild 预构建依赖,提前将项目的第三方依赖格式化为 ESM 模块;
  • 启动一个 node 服务;
  • 打开浏览器,去访问 index.html;
  • 基于浏览器已经支持原生的 ESM 模块,逐步去加载入口文件以及入口文件的依赖模块。浏览器发起请求以后,dev server 端会通过 middlewares 对请求做拦截,然后对源文件做 resolve、load、transform、parse 操作,然后再将转换以后的内容发送给浏览器。

vite 的优点

开发模式下 vite 比 webpack 快的原因:

  • vite 不需要做全量的打包,这是比 webpack 要快的最主要的原因;
  • vite 在解析模块依赖关系时,利用了 esbuild,更快(esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍);
  • 按需加载:模块之间的依赖关系的解析由浏览器实现。Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
  • 充分利用缓存:Vite 利用 HTTP 头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control 进行强缓存,因此一旦被缓存它们将不需要再次请求。

HMR 更快

在热模块 HMR 方面,当修改一个模块的时候,仅需让浏览器重新请求该模块即可,无须像 webpack 那样需要把该模块的相关依赖模块全部编译一次,效率更高。

vite 的缺点

  • 开发环境下首屏加载变慢:由于 unbundle 机制,Vite 首屏期间需要额外做其它工作。由于 unbundle 机制,动态加载的文件,需要做 resolve、load、transform、parse 操作,并且还有大量的 http 请求。不过首屏性能差只发生在 dev server 启动以后第一次加载页面时发生。之后再 reload 页面时,首屏性能会好很多。原因是 dev server 会将之前已经完成转换的内容缓存起来。
  • 开发环境下懒加载变慢:跟首屏加载变慢的原因一样。Vite 在懒加载方面的性能也比 Webpack 差。
  • webpack 兼容性更好,生态更完善。

补充

补充:Vite 在 开发模式 与 生产模式 采用了完全不同的策略:

  • 开发模式:基于浏览器原生 ES Module,由 vite 启动一个轻量 dev server(基于 Connect/Koa)。第三方依赖先用 esbuild 预构建为 ESM 格式(用 Go 写的 bundler,10-100x 速度),源码模块按需即时编译(on-demand transform),不再像 Webpack 一样提前全量打包。
  • 生产模式:用 rollup 打包(输出更干净、体积更小、tree-shaking 更彻底),因为生产环境对兼容性、HMR 没那么敏感,反而对产物大小、首屏速度敏感。
  • 冷启动 vs 首屏:冷启动快(无需全量打包),但首次加载大量模块时会有较多 HTTP 请求;可在 vite.config.js 用 build.rollupOptions.output.manualChunks 优化。
  • HMR 更快:基于 ESM + WebSocket 推送,仅替换变更模块本身,无需重新执行整条 loader 链。

来源整理自:我的有道云笔记