Skip to content
标签
note
字数
1192 字
阅读时间
5 分钟

Webpack

Webpack 会遍历你的应用程序中的所有文件,并启动一个开发服务器,然后将整个代码渲染到开发环境中。

  • webpack 从一个 entry.js 文件开始,将其依赖的所有 js 或者其他 assets 通过 loader 打包成一个文件, 随后这个打包后的文件将被从 server 传递到客户端浏览器运行。

  • 因为这样的处理规则,当保存文件时,整个 JavaScript 包将由 Webpack 重新构建,这就是为什么更改可能需要长达 10 秒才能反映在浏览器中,更新速度会随着应用体积增长而直线下降。


Vite

Vite 的工作方式不同,它不会遍历整个应用程序,Vite 只是转换当时正在使用的文件/模块。

  • Vite 的核心理念:非捆绑开发构建
  • Vite 的核心思想:浏览器请求它时,使用 ES 模块转换并提供一段应用程序代码。

开发构建

在开发环境中,Vite 主要做了两件事情:

  • 基于 Esbuild 打包外部依赖
  • 创建 HTTP Server 以响应浏览器中 <script type="module"> 所发起的一系列模块请求

而生产环境下直接使用 Rollup 进行打包。Vite 整体的优势是在于开发阶段,服务启动快、热更新快,明显地优化了开发者体验。

生产环境不被采用

不少人会吐槽 Vite 开发/生产环境的不一致性,因为开发环境使用 Esbuild + Dev Server 架构,而生产环境直接用 Rollup。但由于生产环境的构建场景和开发阶段存在天然差异,开发和生产表现一致是不现实的。所以问题的核心在于保证生产环境构建的稳定性。

而影响生产构建稳定性最主要的部分在于依赖的处理上,进一步说是对于 CommonJS 格式的依赖处理上面,开发环境使用 Esbuild 而生产环境下使用 @rollup/plugin-commonjs,就容易导致生产构建出现一些奇怪的问题,如 @rollup/plugin-commonjs ignoreTryCatch 行为 github.com/rollup/plug… try-catch 代码块中的 require 语法转换,这样对于某些依赖 (如 jspdf-autotable) 就会出现问题,而开发阶段使用 Esbuild 就不会出现。

解决这类问题有两种方案:

  • 生产环境也使用 Esbuild 来进行依赖的打包,确保 CommonJS 的处理规则和开发阶段一致。该 feature 已经实现,将在 Vite 3.0 发布 github.com/vitejs/vite…

  • 开发和生产阶段使用 ESM CDN 方案,用同一套依赖产物。

模块分类

开始开发构建时,Vite 首先将 JavaScript 模块分为两类:依赖模块和源码模块。

  • 依赖项模块是第三方依赖的代码,从 node_modules 文件夹中导入的 JavaScript 模块。这些模块将使用 esbuild 进行处理和捆绑,esbuild 是一个用 Go 编写的 JavaScript 打包工具,执行速度比 Webpack 快 10-100 倍。
  • 源码模块是源代码,即业务代码,通常涉及特定库的扩展,如:.jsx、.vue、.scss 文件。

具体打包过程

  • 使用基于路由的代码拆分来了解代码的哪些部分实际需要加载,因此,它不必重新打包所有内容。
  • 它还使用现代浏览器中的原生 ES 模块支持来交付代码,这让浏览器可以在开发中承担打包工作
  • 在生产方面,虽然现在所有主流浏览器都支持原生 ES 模块,但它实现了诸如 tree-shaking、延迟加载和通用块拆分等性能优化技术,仍然比非打包应用程序带来更好的整体性能。出于这个原因,Vite 附带了一个预先配置的 build 命令,该命令使用 Rollup 打包来打包和实现各种性能优化。

关于热模块重新加载速度的区别

Webpack 这样的基于打包器的工作流必须在单个浏览器请求之前处理整个 JavaScript 模块

但 Vite 在单个浏览器请求之前只处理依赖模块。这就是为什么 Vite 能够比 Webpack 更快地处理开发构建。

整体性能差异

参考

新朝旧将 vite 和 webpack 煮酒论英雄 - 掘金

Bundle-less 的深入思考和实践 - 掘金

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写