Vite介绍及实现原理

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 | MultiUpdatePayloadif (payload.type === 'multi') {payload.updates.forEach(handleMessage)} else {handleMessage(payload)}
})async function handleMessage(payload: HMRPayload) {const { path, changeSrcPath, timestamp } = payload as UpdatePayloadconsole.log(path)switch (payload.type) {case 'connected':console.log(`[vite] connected.`)breakcase '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.`)}))breakcase '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.`)})breakcase '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.`)breakcase 'js-update':queueUpdate(updateModule(path, changeSrcPath, timestamp))breakcase 'custom':const cbs = customUpdateMap.get(payload.id)if (cbs) {cbs.forEach((cb) => cb(payload.customData))}breakcase '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.pathnameif (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.mzph.cn/news/120944.shtml

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

相关文章

计算机网络——理论知识总结(上)

开新番&#xff0c;因为博主备考的学校计网只考察1/6的分值&#xff0c;而且定位偏向于送分题&#xff0c;因此在备考时并没有很高强度的复习。本帖基于王道考研的教辅总结归纳&#xff0c;虽然是408的教材&#xff0c;但忽略其中有难度的部分&#xff0c;如计算题、画图题等&a…

如何通过员工工时管理降低企业成本?

作为当今快节奏商业环境的领导者或管理者&#xff0c;掌握员工的工作时间对于控制企业成本和确保每个人都各尽其责至关重要。 员工工时表软件就是这样一款工时跟踪管理解决方案&#xff1a;数字化的工时表有助于保护企业的财务不会被无节制的开支冲垮。然而&#xff0c;引入此…

Spark SQL概述与基本操作

目录 一、Spark SQL概述 &#xff08;1&#xff09;概念 &#xff08;2&#xff09;特点 &#xff08;3&#xff09;Spark SQL与Hive异同 &#xff08;4&#xff09;Spark的数据抽象 二、Spark Session对象执行环境构建 (1)Spark Session对象 &#xff08;2&#xff09;代码演…

Flink on yarn 加载失败plugins失效问题解决

Flink on yarn 加载失败plugins失效问题解决 flink版本&#xff1a;1.13.6 1. 问题 flink 任务运行在yarn集群,plugins加载失效,导致通过扩展资源获取任务参数失效 2. 问题定位 yarn容器的jar包及插件信息,jar包是正常上传 源码定位 加载plugins入口&#xff0c;TaskMana…

TCP三次握手具体过程

四次挥手 1&#xff09;客户端进程发出连接释放报文&#xff0c;并且停止发送数据。释放数据报文首部&#xff0c;FIN1&#xff0c;其序列号为sequ&#xff08;等于前已经传送过来的数据的最后一个字节的序号加1)&#xff0c;此时&#xff0c;客户端进入FIN_WAIT_1&#xff08…

AI新能量!FortiGate NGFW面向数据中心全面集成FortiGuard AI 安全服务

企业IT技术正在以惊人的速度发展&#xff0c;转型最大的领域之一是下一代防火墙&#xff08;NGFW&#xff09;市场。如今&#xff0c;混合云、多云、边缘等多种基础设施形态共存&#xff0c;已经成为大部分企业的常态&#xff0c;不断扩张的攻击面需要不同形态防火墙的安全防护…

若依ruoyi-nbcio如何做一个仿钉钉流程设计器的思考

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 看到有些流程图采用仿钉钉的流程设计&#xff0c;比如下面界面&#xff1a; 这种方式虽然简单&#xff0c…

计算机网络文章荟萃

脑残式网络编程入门(二)&#xff1a;我们在读写Socket时&#xff0c;究竟在读写什么&#xff1f;-网络编程/专项技术区 - 即时通讯开发者社区! 1.什么是 socket - 掘金2.socket 的实现原理 - 掘金本文讲述了 socket 在 linux 操作系统下的数据结构&#xff0c;以及阻塞 IO 利用…

檢測項目簡體字

某些項目可能要求代碼中不允許使用簡體字 安裝stcheck檢查 yarn add stcheck --dev在項目根目錄創建 st.config.json 文件 {"patterns": ["./**/*.(ts|js|tsx|jsx|vue|html)","!**/node_modules/**","!.git/**"],"gitignore&q…

Express框架开发接口之登录与注册API

我们利用nodeexpressmysql开发接口&#xff0c;对数据库数据进行简单增、删、查改等操作。 接口是什么&#xff1f; 接口是 前后端通信的桥梁 简单理解&#xff1a;一个接口就是 服务中的一个路由规则 &#xff0c;根据请求响应结果 接口的英文单词是 API (Application Progra…

Java工具库——FastJson的40个常用方法

那些想看却没看的书&#xff0c;在心里摆满一个图书馆… 工具库介绍 阿里巴巴的 FastJSON&#xff0c;也被称为 Alibaba FastJSON 或阿里巴巴 JSON&#xff0c;是一个高性能的 Java JSON 处理库&#xff0c;用于在 Java 应用程序中解析和生成 JSON 数据。FastJSON 以其卓越的性…

HTTP发起请求与收到响应的大致过程

可以《《透视 HTTP 协议》Windows 10 搭建最小实验环境》搭建环境&#xff0c;之后才能进行下边的操作。 1.鼠标左键点击两下www目录下的start.bat批处理文件。 2.打开Wireshark&#xff0c;然后选择Adapter for loopback traffic capture。 3.然后把tcp.port 80 || udp.…

碳排放数据,各地区的(直辖市数据细分到区县),含shp和xlsx格式,带符号化

这两天推了道路相关的数据&#xff0c;道路线路、客运飞机场、航空、地铁、火车站点等等交通出行类的数据之前都已发过&#xff0c;需要的可以自己翻一翻。 交通运输行业还比较关注的碳排放数据&#xff0c;也整理出来了&#xff0c;有需要的自取。 数据地址&#xff1a; 全…

项目管理工具ConceptDraw PROJECT mac中文版自定义列功能

ConceptDraw PROJECT Mac是一款专业的项目管理工具&#xff0c;适用于MacOS平台。它提供了成功规划和执行项目所需的完整功能&#xff0c;包括任务和资源管理、报告和变更控制。 这款软件可以与ConceptDraw office集成&#xff0c;利用思维导图和数据可视化的强大功能来改进项目…

Microsoft.Extensions 简介

Microsoft.Extensions 简介 一、Microsoft.Extensions 简介 .NET Extensions 是一套官方的、开源的、跨平台的 API 集合&#xff0c;提供了一些常用的编程模式和实用工具&#xff0c;例如依赖项注入、日志记录、缓存、Host以及配置等等。该项目的大多数 API 都被用在 .NET 平…

Jetpack:019-Jetpack的导航二(传递数据)

文章目录 1. 知识回顾2. 使用方法2.1 通过参数传递数据2.2 获取参数中的数据2.3 共享导航控制器 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中导航相关的内容&#xff0c;本章回中 继续介绍导航相关的内容。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧…

reactNative导入excel文件

组件内导入 import {TouchableOpacity,PermissionsAndroid} from react-native; import RNFS from react-native-fs; import XLSX from xlsx; import DocumentPicker from react-native-document-picker; import {Buffer} from buffer;// 需要安装一下三个,Buffer和react-nati…

Node编写更新用户头像接口

目录 定义路由和处理函数 验证表单数据 ​编辑 实现更新用户头像的功能 定义路由和处理函数 向外共享定义的更新用户头像处理函数 // 更新用户头像的处理函数 exports.updateAvatar (req, res) > {res.send(更新成功) } 定义更新用户头像路由 // 更新用户头像的路由…

安装 tensorflow==1.15.2 遇见的问题

一、直接安装 命令&#xff1a;pip install tensorflow1.15.2 二、换 阿里云 镜像源 命令&#xff1a;pip install -i http://mirrors.aliyun.com/pypi/simple tensorflow1.15.2 三、换 豆瓣 镜像源 命令&#xff1a;pip install http://pypi.douban.com/simple tensorflow1…

【OpenCV实现平滑图像形态学变化】

文章目录 概要目标腐蚀膨胀开运算结构元素&#xff08;内核&#xff09;小结 概要 形态学变化是一组简单的图像操作&#xff0c;主要用于处理二值图像&#xff0c;即只包含黑和白两种颜色的图像。这些操作通常需要两个输入&#xff0c;原始图像和一个内核&#xff08;kernel&a…