Vite介绍及实现原理

news2024/11/19 22:38:40

Vite介绍及实现原理

  • 一、Vite简介
    • 1.1、什么是Vite
    • 1.2 、Vite的主要特性
    • 1.3、 为什么要使用Vite
  • 二、Vite的实现原理
    • 2.1、依赖处理
    • 2.2、静态资源加载
    • 2.3、vue文件缓存
    • 2.4、 js/ts处理
  • 三、热更新原理
    • 四、vite基本使用
    • 4.1、安装
    • 4.2、搭建项目

一、Vite简介

1.1、什么是Vite

Vite是一种新型的前端构建工具,它能显著改善前端开发体验。

Vite由两个主要部分组成:

  • 一个开发服务器,它基于 原生 ES 模块(ESM),提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
    ESM:ESM是浏览器支持的一种模块化方案,允许在浏览器实现模块化。ES6之前,JS一直没有自己的模块体系。但是ES6引入了ESM,到此,JS终于有了自己的模块体系。
    HMR:全称 Hot Module Replacement,模块热更新,它能够在保持页面状态的情况下动态替换资源模块,提供丝滑顺畅的 Web 页面开发体验。

  • 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源(打包后的体积更小)。
    Rollup:基于ES6的模块打包工具,打包文件小且干净,执行效率更高,更专注于JS打包,同时支持 Tree-shaking
    Tree-shaking:前端中的 tree-shaking 可以理解为通过工具"摇"我们的 JS 文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块 code 摇掉,这样来达到删除无用代码的目的。

Vite作为一个基于浏览器原生ESM的构建工具,它省略了开发环境的打包过程,利用浏览器去解析imports,在服务端按需编译返回。同时,在开发环境拥有速度快到惊人的模块热更新,且热更新的速度不会随着模块增多而变慢。因此,使用Vite进行开发,至少会比Webpack快10倍左右。

1.2 、Vite的主要特性

  • Instant Server Start —— 即时服务启动
  • Lightning Fast HMR —— 闪电般快速的热更新
  • Rich Features —— 丰富的功能
  • Optimized Build —— 经过优化的构建

1.3、 为什么要使用Vite

  • 开发环境⚡️速度的提升
    使用 JavaScript 开发的工具通常需要很长的时间才能启动开发服务器,且这个启动时间与代码量、代码复杂度正相关。即使使用HMR,文件修改后的效果也要几秒钟才能在浏览器中反应出来,代表如Webpack。那么Vite是如何解决如Webpack这样的构建工具一样,在复杂、多模块项目开发中启动慢、HMR慢的问题呢?
    我们详细对比了开发环境中的ViteWebpack,发现主要有如下不同:
WebpackVite
先打包生成bundle(经过Webpack打包后的静态资源文件),再启动开发服务器先启动开发服务器,利用新一代浏览器的ESM能力,无需打包,直接请求所需模块并实时编译
HMR时需要把改动模块及相关依赖全部编译HMR时只需让浏览器重新请求该模块,同时利用浏览器的缓存(源码模块协商缓存,依赖模块强缓存)来优化请求

因此,针对开发环境中的启动慢问题,Vite开发环境冷启动无需打包,无需分析模块之间的依赖,同时也无需在启动开发服务器前进行编译,启动时还会使用 esbuild预构建依赖 来进行预构建。
Webpack 启动后会做一堆事情,经历一条很长的编译打包链条,从入口开始需要逐步经历语法解析、依赖收集、代码转译、打包合并、代码优化,最终将高版本的、离散的源码编译打包成低版本、高兼容性的产物代码,这可满满都是 CPU、IO 操作啊,在 Node 运行时下性能必然是有问题。

针对HMR慢,即使只有很小的改动,Webpack依然需要构建完整的模块依赖图,并根据依赖图来进行转换。而Vite利用了ESM浏览器缓存技术,更新速度与项目复杂度无关。可以看到,Vite构建工具,在开发环境启动时只需要启动两个Server,一个用于页面加载,一个用于HMR的Websocket。当浏览器发出原生的ESM请求,Server收到请求只需要编译当前文件后返回给浏览器,不需要管理依赖。

在这里插入图片描述
在这里插入图片描述

  • 使用简单,开箱即用
    相比Webpack需要对entry、loader、plugin等进行诸多配置,Vite的使用可谓是相当简单了。只需执行初始化命令,就可以得到一个预设好的开发环境,开箱即获得一堆功能,包括:CSS预处理、html预处理、异步加载、分包、压缩、HMR等。他只是暴露了极少数的配置项和plugin接口,不会像Webpack一样需要了解庞大的loader、plugin生态,灵活适中、复杂度适中。适合前端新手。

二、Vite的实现原理

Vite 的基本实现原理,就是启动一个 koa 服务器拦截由浏览器请求 ESM的请求。通过请求的路径找到目录下对应的文件做一定的处理最终以 ESM的格式返回给客户端。

  • Koa是一个基于Node.js的Web框架,它提供了一种更小巧、更高效的方式来构建Web应用程序。
    在这里插入图片描述

2.1、依赖处理

Vite 通过在一开始将应用中的模块区分为 依赖源码 两类,改进了开发服务器启动时间。依赖 大多为在开发时不会变动的纯 JavaScript。

  • 依赖解析
    以 Vite 官方 demo 为例,当我们请求 localhost:3000 时,Vite 默认返回 localhost:3000/index.html 的代码。而后发送请求 src/main.js
    main.js 代码如下:
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

createApp(App).mount('#app')

在这里插入图片描述
可以观察到浏览器请求 vue.js 时, 请求路径是 @modules/vue.js。在 Vite 中约定若 path 的请求路径满足 /^\/@modules\// 格式时,被认为是一个 node_modules 模块。
首先正则匹配请求路径,如果是/@modules开头就进行后续处理,否则就跳过。若是,会设置响应类型为js,读取真实模块路径内容,返回给客户端(即浏览器)。
客户端注入本质上是创建一个script标签(type=‘module’),然后将其插入到head中,这样客户端在解析html是就可以执行代码了。

  • 依赖预构建
    Vite 将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能。

    Vite使用esbuild在初次启动开发服务器前把检测到的依赖进行预构建。Vite 基于ESM,在使用某些模块时,由于模块依赖了另一些模块,依赖的模块又基于另一些模块。会出现页面初始化时一次发送数百个模块请求的情况。

    lodash-es 为例,代码中以 import { debounce } from 'lodash' 导入一个命名函数时候,并不是只下载包含这个函数的文件,而是有一个依赖图。
    在这里插入图片描述
    可以看到一共发送了651个请求。一共花费1.53s。
    在这里插入图片描述
    Vite 为了优化这个情况,利用esbuild在启动的时候预先把debounce用到的所有内部模块全部打包成一个bundle,这样就浏览器在请求debounce时,便只需要发送一次请求了。
    可以看到预构建后,lodash-es只发送了1个请求。
    在这里插入图片描述

2.2、静态资源加载

当请求的路径符合 imageRE, mediaRE, fontsRE 或 JSON 格式,会被认为是一个静态资源。静态资源将处理成ESM模块返回。

const imageRE = /\.(png|jpe?g|gif|svg|ico|webp)(\?.*)?$/
const mediaRE = /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/
const fontsRE = /\.(woff2?|eot|ttf|otf)(\?.*)?$/i

2.3、vue文件缓存

当 Vite 遇到一个 .vue 后缀的文件时。由于 .vue 模板文件的特殊性,它被拆分成 template, css, script 模块三个模块进行分别处理。最后会对 script, template, css 发送多个请求获取。
在这里插入图片描述
如上图中请求 App.vue 获取script 代码 , App.vue?type=template 获取 template, App.vue?type=style。这些代码都被插入在 App.vue 返回的代码中。
在这里插入图片描述

2.4、 js/ts处理

Vite使用esbuild将ts转译到js,约是tsc速度的20~30倍,同时HMR更新反应到浏览器的时间会小于50ms。但是,由于esbuild转换ts到js对于类型操作仅仅是擦除,所以完全保证不了类型正确,因此需要额外校验类型,比如使用tsc --noEmit

  • tsc是TypeScript为我们提供的一个命令行工具(CLI)。

将ts转换成js后,浏览器便可以利用ESM直接拿到js资源。

三、热更新原理

Vite 的热更新原理,其实就是在客户端与服务端建立了一个 websocket 连接,当代码被修改时,服务端发送消息通知客户端去请求修改模块的代码,完成热更新。

  • 服务端:服务端做的就是监听代码文件的改变,在合适的时机向客户端发送 websocket 信息通知客户端去请求新的模块代码。
  • 客户端(浏览器):Vite 中客户端的 websocket 相关代码在处理 html 中时被写入代码中。可以看到在处理 html 时,vite/client 的相关代码已经被插入。
export const clientPublicPath = `/vite/client`
const devInjectionCode = `\n<script type="module">import "${clientPublicPath}"</script>\n`
async function rewriteHtml(importer: string, html: string) {
  return injectScriptToHtml(html, devInjectionCode)
}

当request.path 路径是 /vite/client 时,请求获取已经提前写好的关于 websocket 的代码。因此在客户端中我们创建了一个 websocket 服务并与服务端建立了连接。

Vite 会接受到来自客户端的消息。通过不同的消息触发一些事件。做到浏览器端的即时热模块更换(热更新)。包括 connect、vue-reload、vue-rerender 等事件,分别触发组件vue 的重新加载,render等。

// Listen for messages
socket.addEventListener('message', async ({ data }) => {
  const payload = JSON.parse(data) as HMRPayload | MultiUpdatePayload
  if (payload.type === 'multi') {
    payload.updates.forEach(handleMessage)
  } else {
    handleMessage(payload)
  }
})

async function handleMessage(payload: HMRPayload) {
  const { path, changeSrcPath, timestamp } = payload as UpdatePayload
  console.log(path)
  switch (payload.type) {
    case 'connected':
      console.log(`[vite] connected.`)
      break
    case 'vue-reload':
      queueUpdate(
        import(`${path}?t=${timestamp}`)
          .catch((err) => warnFailedFetch(err, path))
          .then((m) => () => {
            __VUE_HMR_RUNTIME__.reload(path, m.default)
            console.log(`[vite] ${path} reloaded.`)
          })
      )
      break
    case 'vue-rerender':
      const templatePath = `${path}?type=template`
      import(`${templatePath}&t=${timestamp}`).then((m) => {
        __VUE_HMR_RUNTIME__.rerender(path, m.render)
        console.log(`[vite] ${path} template updated.`)
      })
      break
    case 'style-update':
      // check if this is referenced in html via <link>
      const el = document.querySelector(`link[href*='${path}']`)
      if (el) {
        el.setAttribute(
          'href',
          `${path}${path.includes('?') ? '&' : '?'}t=${timestamp}`
        )
        break
      }
      const importQuery = path.includes('?') ? '&import' : '?import'
      await import(`${path}${importQuery}&t=${timestamp}`)
      console.log(`[vite] ${path} updated.`)
      break
    case 'js-update':
      queueUpdate(updateModule(path, changeSrcPath, timestamp))
      break
    case 'custom':
      const cbs = customUpdateMap.get(payload.id)
      if (cbs) {
        cbs.forEach((cb) => cb(payload.customData))
      }
      break
    case 'full-reload':
      if (path.endsWith('.html')) {
        // if html file is edited, only reload the page if the browser is
        // currently on that page.
        const pagePath = location.pathname
        if (
          pagePath === path ||
          (pagePath.endsWith('/') && pagePath + 'index.html' === path)
        ) {
          location.reload()
        }
        return
      } else {
       location.reload()
      }
  }
}

四、vite基本使用

4.1、安装

兼容性注意
Vite 需要 Node.js 版本 >= 12.0.0。

$ npm init vite@latest

4.2、搭建项目

# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue
# vite+ts
npm init vite@latest my-vue-app -- --template vue-ts

Vite 官方对 Vue 的支持只针对于Vue3.x 版本,而对于 Vue2.x 是不支持的。使 Vite 支持 Vue2.x,是需要安装插件来实现。
https://www.vitejs.net

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1124420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“中国版Zara”拉夏贝尔:从辉煌到破产清算

文/ 大力财经 拉夏贝尔的破产清算&#xff0c;让人不禁惋惜。这个曾经被誉为“中国版Zara”的女装品牌&#xff0c;在全国拥有超过2000家门店&#xff0c;一度是年轻人的追捧对象。 然而&#xff0c;由于市场竞争激烈、品牌定位模糊、库存积压严重等问题&#xff0c;拉夏贝尔…

数字人扫描对虚拟人三维动画宣传片制作有何作用?

近日&#xff0c;周杰伦超写实数智人“周同学”首支元宇宙先导片《次元拓》在演唱会现场进行了全球首发&#xff0c;通过对实景拍摄一比一还原&#xff0c;打造出一个多重混合现实的元宇宙世界&#xff0c;展现出逼真的视觉效果&#xff0c;为粉丝和大众带来了一场科技的视觉盛…

idea免费插件分享

分享一些在开发中常用到的idea插件&#xff0c;都是一些我自己常用的&#xff0c;希望对各位程序员有帮助吧。 1、Chinese Language 汉化插件&#xff1a;中文语言包将为您的 IntelliJ IDEA, AppCode, CLion, DataGrip, GoLand, PyCharm, PhpStorm, RubyMine, WebStorm, 和Rid…

【备忘录】修复docker环境下的nacos安全漏洞:身份认证绕过漏洞

文章目录 一、漏洞复现1.1 访问登录口用户名输入nacos密码输入任意值&#xff0c;进行抓包1.2 伪造登录凭证1.3 登录包中新加入一项凭证验证 二、漏洞解决2.1 分析原因2.2 解决方案2.3 操作留痕1、先了解nacos部署环境2、查看比对配置文件3、修改配置文件后&#xff0c;重启 一…

单链表,三部分详解(第一部分)单链表的解析

1. 链表的概念及结构 链表就是一个在物理储存上非连续&#xff0c;但在逻辑顺序上是连续的指针链接实现。 链表就像一大节火车&#xff0c;你在淡季的时候可以把车厢减少一点&#xff0c;旺季的 时候可以多加一点&#xff0c;不会影响其他车厢的使用。每节车厢都独立存在。 那我…

Hadoop+Hive+Spark+Hbase开发环境练习

1.练习一 1.数据准备 在hdfs上创建文件夹&#xff0c;上传csv文件 [rootkb129 ~]# hdfs dfs -mkdir -p /app/data/exam 查看csv文件行数 [rootkb129 ~]# hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l 2.分别使用 RDD和 Spark SQL 完成以下分析&#xf…

【环境】Linux下Anaconda/ Miniconda安装+百度Paddle环境搭建+Cudnn(3090显卡+CUDA11.8+cudnn8.6.0)

清华源帮助链接&#xff1a;https://mirror.tuna.tsinghua.edu.cn/help/anaconda/ 下载链接&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 其他深度学习环境相关博文&#xff1a;【stable-diffusion】4090显卡下dreambooth、lora、sd模型微调的GUI环境…

没有英语要求的中国人大女王金融硕士有多香你可能还不知道

在当今全球化的世界中&#xff0c;英语已经成为了一种国际通用语言。对于许多学生来说&#xff0c;掌握英语是实现个人发展和职业成功的关键。尤其是在读研阶段&#xff0c;英语水平的要求更是不容忽视。但现实问题是我们没有相应的语言环境&#xff0c;直接导致的是大学的英语…

GPR 子波 一阶微分高斯脉冲和Ricker子波

gprMAX仿真时 用ricker子波&#xff0c;被审稿人咨询为什么用ricker波&#xff1f; 咨询了GPR设计专家&#xff0c;地耦雷达会用一阶高斯微分&#xff0c;空藕用ricker子波。实际上&#xff0c;我们都么有考虑这个。 给出matlab绘制代码 1 高斯脉冲 1.1 代码 % Parameters…

docker-rabbitmq 安装依赖

出现的问题如下: channel error; protocol method: #method(reply-code404, reply-textNOT_FOUND - no channel error&#xff1b; protocol method: #method&#xff1c;channel.close&#xff1e;(reply-code404, reply-textNOT_FOUND - no 查看rabbitmq 客户端是否存在如…

几千粉丝的视频账号播放量只有几百怎么办?借助批量剪辑快速提升播放量

为什么很多人的短视频账号明明有几千粉丝&#xff0c;但是发的作品却只有几百的播放量&#xff1f; 其实原因很简单&#xff0c;大多数人在起号的时候都会犯一个低级错误——盲目追求粉丝数量&#xff0c;而不在意粉丝质量。 做付费流量都懂&#xff1a;越是便宜的粉&#xf…

【会议征稿通知】第三届密码学、网络安全和通信技术国际会议(CNSCT 2024)

第三届密码学、网络安全和通信技术国际会议&#xff08;CNSCT 2024&#xff09; 2024 3rd International Conference on Cryptography, Network Security and Communication Technology 随着互联网和网络应用的不断发展&#xff0c;网络安全在计算机科学中的地位越来越重要&…

linux elf relationship between data structures involved in symbol resolution

When a program imports a certain function or variable, the linker will include a string with the function or variable’s name in the .dynstr section. A symbol (Elf Sym) that refers to the function or variable’s name in the .dynsym section, and a relocati…

vue面试题及答案【集合目录】

前言&#xff1a; 欢迎浏览和关注本专栏《 前端就业宝典 》&#xff0c; 不管是扭螺丝还是造火箭&#xff0c; 多学点知识总没错。 这个专栏是扭螺丝之上要造火箭级别的知识&#xff0c;会给前端工作学习的小伙伴带来意想不到的帮助。 本专栏将前端知识拆整为零&#xff0c;主要…

UI自动化测试,让测试高效起来

RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度可复用的测试脚本&#xff0c;测试团队无需复杂的代码编写即可开展低代码的自动化…

软考-des题目案例

1.补全图片中的数字 &#xff08;1&#xff09;10 &#xff0c;&#xff08;2&#xff09;6&#xff0c;&#xff08;3&#xff09;1&#xff0c;&#xff08;4&#xff09;11 2.初始置换简单计算 置换时&#xff0c;从左上角的第一个元素开始&#xff0c;表示输入的明文的第5…

中国人民大学金融加拿大女王大学硕士项目:中外名校强强联手,共同打造金融精英

随着全球经济一体化的不断深入&#xff0c;金融行业在国际竞争中的地位日益凸显。为了培养具有国际视野、创新精神和实践能力的金融人才&#xff0c;中国人民大学与加拿大女王大学携手合作&#xff0c;共同打造了金融硕士项目。人大女王金融硕士项目旨在为学生提供世界一流的教…

sshd 解决问题 Deprecated SSH Cryptographic Settings 通过修改配置 去掉废弃的加密算法

sshd 解决问题 Deprecated SSH Cryptographic Settings 通过修改配置 去掉废弃的加密算法 证实无效, 有效解决办法是升级 openssh到最新版本,可以 yum 或者 编译安装 漏洞检测报说 使用废弃的加密算法 aes128-cbc aes256-cbc我们通过配置文件来去掉这两个算法,只保留系统中的…

使用Ubuntu系统搭建RabbitMQ服务并结合内网穿透实现公网访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

labelimg使用以及xml和txt转化

一、使用 winr——输入cmd 激活已有的环境 conda activate torch1.2.0 下载lebelme pip install labelme3.16.7 再输入labelme打开软件就可 可以设置自动保存&#xff0c;View——auto save mode打上勾 二、注意 1.自己类的定义名称&#xff0c;在txt中是0&#xff0c;1&a…