Vite 原理浅析

在这里插入图片描述

Vite有如下特点:

  • 快速的冷启动: No Bundle + esbuild 预构建
  • 即时的模块热更新: 基于ESM的HMR,同时利用浏览器缓存策略提升速度
  • 真正的按需加载: 利用浏览器ESM支持,实现真正的按需加载

Vite相比于Webpack而言,没有打包的过程,而是直接启动了一个开发服务器devServer。Vite劫持浏览器的HTTP请求,在后端进行相应的处理将项目中使用的文件通过简单的分解与整合,然后再返回给浏览器(整个过程没有对文件进行打包编译)。所以编译速度很快。

Vite 直接整合了 Rollup,为用户提供了完善、开箱即用的解决方案,在需要bundle打包的时候Vite 使用 Rollup 内置配置。

ESM是JavaScript提出的官方标准化模块系统,不同于之前的CJS,AMD,CMD等等,ESM提供了更原生以及更动态的模块加载方案,最重要的就是它是浏览器原生支持的,也就是说我们可以直接在浏览器中去执行import,动态引入我们需要的模块,而不是把所有模块打包在一起

当我们在使用模块开发时,其实就是在构建一张模块依赖关系图,当模块加载时,就会从入口文件开始,最终生成完整的模块实例图。

ESM的执行可以分为三个步骤:

  1. 构建: 确定从哪里下载该模块文件、下载并将所有的文件解析为模块记录

  2. 实例化: 将模块记录转换为一个模块实例,为所有的模块分配内存空间,依照导出、导入语句把模块指向对应的内存地址

  3. 运行:运行代码,将内存空间填充

ESM使用实时绑定的模式,导出和导入的模块都指向相同的内存地址,也就是值引用。而CJS采用的是值拷贝,即所有导出值都是拷贝值。

Vite 核心原理

Vite其核心原理是利用浏览器现在已经支持ES6的import,碰见import就会发送一个HTTP请求去加载文件。Vite启动一个 connect 服务器拦截这些请求,并在后端进行相应的处理将项目中使用的文件通过简单的分解与整合,然后再以ESM格式返回返回给浏览器。整个过程中没有对文件进行打包编译。

Webpack是先解析依赖、打包构建再启动开发服务器,Dev Server 必须等待所有模块构建完成,当我们修改了 bundle模块中的一个子模块, 整个 bundle 文件都会重新打包然后输出。项目应用越大,启动时间越长。

而 Vite利用浏览器对ESM的支持,当 import 模块时,浏览器就会下载被导入的模块。先启动开发服务器,当代码执行到模块加载时再请求对应模块的文件,本质上实现了动态加载。

目前所有的打包工具实现热更新的思路都大同小异:主要是通过WebSocket创建浏览器和服务器的通信监听文件的改变,当文件被修改时,服务端发送消息通知客户端修改相应的代码,客户端对应不同的文件进行不同的操作的更新。

Vite 通过 chokidar 来监听文件系统的变更,只用对发生变更的模块重新加载, 只需要精确的使相关模块与其临近的 HMR边界连接失效即可,这样HMR 更新速度就不会因为应用体积的增加而变慢。

热更新流程

Vite整个热更新过程可以分成四步:

  1. 创建一个websocket服务端和client文件,启动服务
  2. 通过chokidar监听文件变更
  3. 当代码变更后,服务端进行判断并推送到客户端
  4. 客户端根据推送的信息执行不同操作的更新
  • 启动热更新:createWebSocketServer: 在 Vite dev server 启动之前,Vite 会为 HMR 做一些准备工作:比如创建websocket服务,利用chokidar创建一个监听对象 watcher 用于对文件修改进行监听等等。createWebSocketServer这个方法主要是创建WebSocket服务并对错误进行一些处理,最后返回封装好的on、off、 send 和 close 方法,用于后续服务端推送消息和关闭服务

  • 执行热更新:moduleGraph+handleHMRUpdate模块。接收到文件改动执行的回调,这里主要两个操作:moduleGraph.onFileChange修改文件的缓存和handleHMRUpdate执行热更新。moduleGraph 是Vite定义的用来记录整个应用的模块依赖图的类,除此之外还有moduleNode。moduleGraph是由一系列 map 组成,而这些map分别是url、id、file等与ModuleNode的映射,而ModuleNode 是 Vite中定义的最小模块单位。

  • handleHMRUpdate: 主要是监听文件的更改,进行处理和判断通过WebSocket给客户端发送消息通知客户端去请求新的模块代码。

预编译原理

Vite预编译之后,将文件缓存在node_modules/.vite/文件夹下。根据以下地方来决定是否需要重新执行预构建。

  • package.json中:dependencies发生变化
  • 包管理器的lockfile

如果想强制让Vite重新预构建依赖,可以使用–force启动开发服务器,或者直接删掉node_modules/.vite/文件夹。

### Vue 和 Vite 工作原理及构建机制 #### 1. Vue.js 的工作原理 Vue.js 是一个渐进式的 JavaScript 框架,其设计目标是提供简单易用的 API 同时保持高性能。以下是 Vue.js 的一些核心特性和工作机制: - **响应式系统** Vue 使用了一个基于对象属性观察器(`Object.defineProperty` 或 `Proxy`)的响应式系统来追踪数据变化并自动更新视图[^1]。在 Vue 3 中引入了 Proxy 替代 Object.defineProperty,这使得响应式系统的性能更高且支持更复杂的数据结构。 - **虚拟 DOM (Virtual DOM)** 虚拟 DOM 是 Vue 实现高效界面更新的关键技术之一。当状态发生变化时,Vue 不会直接操作真实 DOM,而是先创建一个新的虚拟 DOM 树并与之前的树进行比较(diff 算法),仅对有差异的部分执行最小化的真实 DOM 更新。 - **组件化开发** 组件是 Vue 应用程序的基本单元,允许开发者将 UI 划分为独立可重用的小型模块。每个组件都有自己的模板、逻辑和样式,并可以通过 props 和 events 进行通信。 - **生命周期钩子** Vue 提供了一系列生命周期方法,让开发者能够在特定阶段介入组件的行为,比如初始化 (`created`)、挂载完成 (`mounted`) 等。 --- #### 2. Vite 的工作原理 Vite 是由 Vue 团队推出的新一代前端构建工具,旨在解决传统打包工具(如 Webpack)在大型项目中启动慢的问题。它的主要特点如下: - **开发环境下的原生 ESM 支持** 在开发模式下,Vite 并不依赖传统的打包过程,而是利用现代浏览器对 ES Module 的原生支持,通过 HTTP 请求动态加载 `.js` 文件及其依赖项[^2]。这种按需加载的方式显著提高了冷启动速度。 - **即时模块热更新 (HMR)** 当源码发生更改时,Vite 只重新加载受影响的模块而不是整个页面,从而实现极快的反馈循环。对于单文件组件 (.vue),Vite 将它们分割成 script、template 和 style 部分分别处理[^4]。 - **生产环境优化** 对于生产部署,Vite 使用 Rollup 来预打包第三方依赖并将最终产物压缩为高效的静态资源文件集合。相比 Webpack,这种方法减少了运行时开销并提升了加载效率。 --- #### 3. 如何初始化 Vite 项目? 要快速搭建一个基于 Vite 的 Vue 项目,可以使用官方推荐的一键脚手架命令: ```bash npm create vite@latest . -- --template vue ``` 该命令会下载最新的 Vite 版本以及配置好默认设置好的 Vue 模板[^3]。需要注意的是,由于这是针对最新稳定版的操作方式,因此可能会遇到某些旧版本 Node.js 下无法正常工作的场景。 --- #### 4. 总结 综上所述,Vue.js 凭借强大的响应式引擎、轻量级的设计理念成为主流框架;而作为新一代构建利器的 Vite,则凭借极速启动时间与智能化 HMR 成为了现代化开发流程的理想选择。两者相结合能够极大程度简化日常编码体验的同时保障应用质量。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蟹蟹蟹风流

期望和你分享一杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值