跳到主要内容

认识

一、认识


Vite 是一个前端开发与构建工具。采用双引擎架构, 开发阶段使用 Esbuild + no-bundle 服务,生产环境用 Rollup 编译构建。

Vite在开发阶段, Vite 项目的启动可以分为两步。第一步是依赖预构建,借助 Esbuild 超快的编译速度来做第三方库构建和 TS/JSX 语法编译, 第二步是 Dev Server 的启动, 基于浏览器原生 ESModule 的支持实现了 no-bundle 服务,实现开发阶段的 Dev Server, 进行模块的按需加载, 可以直接在浏览器中运行源码, 无需事先打包。每一个文件请求进来都会经历一系列的编译流程,然后 Vite 会将编译结果响应给浏览器。

Vite 生产环境借助 Rollup, 从 AST 解析的功能开始,完成代码的词法分析(tokenize)和语义分析(parse),实现模块依赖图和作用域链的搭建,并完成 Tree Shaking、循环依赖检测及 Bundle 代码生成

Preview

二、特点


2.1 极速的服务启动

极速的服务启动: 使用原生 ESM 文件,无需打包!

2.2 轻量快速的热重载

轻量快速的热重载: 无论应用程序大小如何,都始终极快的模块热替换(HMR

三、问题


3.1 Vite、Rollup、Webpack、RsPack 各自优势、特点?

Vite: 采用双引擎架构, 开发阶段使用 Esbuild + no-bundle 服务,生产环境用 Rollup 编译构建。Vite在开发阶段, Vite 项目的启动可以分为两步。第一步是 依赖预构建, 借助 Esbuild 超快的编译速度来将不同规范的代码转换为 ES Module 格式, 方便浏览器直接加载, 此外, 预构建还会将第三方库分散的文件合并打包到一起, 减少 HTTP 请求数量; 第二步是 Dev Server 的启动, 基于浏览器原生 ESModule 的支持实现了 no-bundle 服务,实现开发阶段的 Dev Server, 进行模块的按需加载, 可以直接在浏览器中运行源码, 无需事先打包。当浏览器请求一个模块时, Vite 会即时地编译和执行对应的代码, 会经历一系列的编译流程, 然后 Vite 会将编译结果响应给浏览器。Vite 生产环境借助 Rollup, 从 AST 解析的功能开始, 完成代码的词法分析(tokenize)和语义分析(parse), 实现模块依赖图和作用域链的搭建, 并完成 Tree Shaking、循环依赖检测及 Bundle 代码生成。 在 HMR 方面, Vite 的热更新则只会针对改动的模块进行更新,提高了更新速度。当开发者修改了一个模块的代码, Vite 可以在几毫秒内完成热更新, 将更新后的模块发送到浏览器中, 让开发者能够更快地看到代码修改后的效果。

Rollup 是一款基于 ES Module 模块规范实现的 JavaScript 打包工具。通过静态分析构建模块依赖图, 并进行 Tree Shaking, 剔除未使用的代码。Rollup 可以直接处理 Es Modules , 对于 CommonJs 需要通过插件来转换。Rollup 本身不提供开发服务器、HMR 等功能,主要定位于生产构建。

Webpack: 无论开发环境还是生产环境, Webpack 会扫描整个项目的所有文件, 将所有模块进行静态分析, 分析它们之间的依赖关系, 形成依赖树, 然后一次性编译生成文件, 生成最终代码前, 根据模块中出现的特性依赖, 补充相应运行时代码, 比如立即表达式 IIFEWebpack runtime 运行时代码, 生成最终产物。Webpack 实现了一套自己的 CommonJS 规范, 在 Webpack 中, 每个模块都被包装在一个函数中, 这个函数接受一个对象, 这个对象有 exportsrequiremodule 等属性, 通过这种方式实现了模块的隔离, 每个模块都有自己的作用域, 不会污染全局作用域。在 HMR 方面, Webpack 的热更新需要整个模块链重新打包和替换,对于大型项目可能会有延迟。在热更新过程中, Webpack 会检测到模块的变化,然后重新编译整个模块链,最后将更新后的模块替换到浏览器中。这个过程相对复杂,可能会导致一定的延迟。另外, Webpack 5.x 内置了更加完善、更智能、更强大的 TreeShaking代码分割作用域提升 等。Webpack 5.x 新特性: 1. 模块联邦(Module Federation, 模块联邦是 Webpack 5 中最引人注目的新特性之一, 它允许不同独立构建的应用在运行时共享彼此的模块,而无需事先打包到同一个 bundle 里; 2. 持久化缓存(Persistent Caching, Webpack 5 引入了持久化缓存功能,将中间构建结果保存到磁盘上,这样在二次构建时可以复用已有结果; 3. 更高效的 Tree Shaking 与代码优化: 使生成的产物更精简,提升浏览器缓存效果; 4. 删除 Node.js 核心模块的自动 Polyfill, 以前 Webpack 会自动为浏览器端补充 Node.js 核心模块(例如 Bufferprocesscrypto 等)的 polyfill, Webpack 5 默认不再提供这些 polyfill, 要求开发者根据项目需要手动添加或调整代码逻辑; 5. 内置资源模块(Asset Modules, 在 Webpack 4 及之前版本中,处理静态资源(如图片、字体等)通常依赖于第三方 Loader(如 file-loaderurl-loaderraw-loader 等), Webpack 5 内置了资源模块,开发者可以直接在代码中 import 资源, 无需额外安装 Loader

RsPack 是一个基于 Rust 编写的高性能 JavaScript 打包工具, 它提供对 Webpack 生态良好的兼容性,能够无缝替换 Webpack, 并提供闪电般的构建速度。1. Rust 语言优势: Rspack 使用 Rust 语言编写, 得益于 Rust 的高性能编译器支持, Rust 编译生成的 Native Code 通常比 JavaScript 性能更为高效; 2. 高度并行的架构: Webpack 受限于 JavaScript 对多线程的羸弱支持,导致其很难进行高度的并行化计算,而得益于 Rust 语言的并行化的良好支持, Rspack 采用了高度并行化的架构,如模块图生成,代码生成等阶段,都是采用多线程并行执行,这使得其编译性能随着 CPU 核心数的增长而增长,充分挖掘 CPU 的多核优势; 3. 内置大部分的功能: 事实上 Webpack 本身的性能足够高效,但是因为 Webpack 本身内置了较少的功能,这使得我们在使用 Webpack 做现代 Web App 开发时,通常需要配合很多的 pluginloader 进行使用,而这些 loaderplugin 往往是性能的瓶颈,而 Rspack 虽然支持 loaderplugin,但是保证绝大部分常用功能都内置在 Rspack 内,从而减小 JS plugin | loader 导致的低性能和通信开销问题; 4. 增量编译: 尽管 Rspack 的全量编译足够高效,但是当项目庞大时,全量的编译仍然难以满足 HMR 的性能要求,因此在 HMR 阶段,我们采用的是更为高效的增量编译策略,从而保证,无论你的项目多大,其 HMR 的开销总是控制在合理范围内。但是, RsPackWebpack 对构建产物体积的优化方面, TreeShaking代码分割作用域提升 做的不是那么完善。

扩展知识


bundlechunk、**vendor**这些构建领域的专业概念,这里给大家提前解释一下:

  • bundle 指的是整体的打包产物,包含 JS 和各种静态资源。

  • chunk 指的是打包后的 JS 文件,是 bundle 的子集。

  • vendor 是指第三方包的打包产物,是一种特殊的 chunk

参考资料


深入浅出 Vite