Vite构建,用NodeJS搭建一个简单的Vite服务
Vite 是一个现代的前端构建工具,由 Vue.js 作者尤雨溪创建。它主要用于开发和构建现代 JavaScript 应用,尤其是单页应用(SPA)。Vite 相比于传统的构建工具(如 Webpack)有几个显著的优势:
- 即时开发服务器:Vite 利用原生 ES 模块(ESM)在浏览器中提供模块热更新(HMR),这使得开发体验更加快速和流畅。
- 按需编译:Vite 只编译和打包你当前需要的部分,而不是整个项目,这大大减少了初始构建时间。
- 插件系统:Vite 提供了一个简单而强大的插件系统,使得集成第三方工具和库变得容易。
Vite 构建过程及其原理
1. 启动开发服务器
- 监听文件变化:Vite 使用
esbuild或 Rollup 作为其底层打包工具,启动一个开发服务器并监听文件系统的变化。 - 模块解析:当文件发生变化时,Vite 会解析并转换模块,利用原生 ESM 特性进行模块的动态加载。
- 热模块替换(HMR):Vite 支持热模块替换,使得你可以在不刷新页面的情况下更新模块。
2. 构建生产代码
- 代码分割:Vite 会根据模块间的依赖关系进行代码分割,以减少初始加载时间。
- Tree Shaking:通过静态分析,移除未使用的代码,减少打包体积。
- 优化:包括 CSS 提取、图片压缩、代码混淆等优化步骤。
用 Node.js 写一个简单的 Vite 服务
虽然 Vite 本身是一个复杂的工具,但我们可以创建一个简单的 Node.js 服务器来模拟 Vite 的一些基本功能,比如提供静态文件服务和热更新(尽管实现完整的 HMR 功能会复杂得多)。
以下是一个简单的 Node.js 服务器示例,可以提供静态文件服务:
const http = require('http');
const fs = require('fs');
const path = require('path');
const chokidar = require('chokidar');const PORT = 3000;
const DIST_DIR = path.join(__dirname, 'dist');// 创建 HTTP 服务器
const server = http.createServer((req, res) => {const filePath = '.' + req.url;if (filePath == './') {filePath = './index.html';}const fileExists = fs.existsSync(path.join(DIST_DIR, filePath));if (fileExists) {const fileStream = fs.createReadStream(path.join(DIST_DIR, filePath));const contentType = getContentType(filePath);res.writeHead(200, { 'Content-Type': contentType });fileStream.pipe(res);} else {res.writeHead(404, { 'Content-Type': 'text/plain' });res.end('File not found');}
});// 获取文件内容类型
function getContentType(filePath) {const extname = path.extname(filePath);switch (extname) {case '.html':return 'text/html';case '.css':return 'text/css';case '.js':return 'application/javascript';case '.json':return 'application/json';case '.png':return 'image/png';case '.jpg':return 'image/jpeg';default:return 'application/octet-stream';}
}// 监听文件变化
const watcher = chokidar.watch(DIST_DIR, { ignored: /(^|[\/\\])\../, persistent: true });watcher.on('add', path => logChange('added', path)).on('change', path => logChange('changed', path)).on('unlink', path => logChange('removed', path));function logChange(eventType, filePath) {console.log(`File ${eventType}: ${filePath}`);// 这里可以添加逻辑来通知客户端文件已经改变(简单的 HMR 逻辑)// 例如,通过 WebSocket 发送消息给客户端
}// 启动服务器
server.listen(PORT, () => {console.log(`Server is running on http://localhost:${PORT}`);
});
说明
- 静态文件服务:这个简单的服务器会提供
dist目录下的静态文件。 - 文件监听:使用
chokidar库监听dist目录下的文件变化,并在控制台打印文件变化的信息。 - 内容类型:根据文件扩展名设置正确的
Content-Type。
注意事项
- 这个简单的服务器并没有实现 Vite 的核心功能,比如按需编译和热模块替换(HMR)。
- 实际的 Vite 使用了更多的高级特性和技术,包括 Rollup 或 esbuild 的打包能力、插件系统、CSS 和图片处理等。
- 如果你需要更高级的功能,建议使用 Vite 官方提供的工具。
希望这个简单的示例能帮助你理解 Vite 的一些基本概念和原理。如果你对 Vite 感兴趣,建议深入阅读其官方文档和源代码。
Vite实现即时编译的关键在于其独特的设计和对现代浏览器特性的充分利用。以下是Vite实现即时编译的主要步骤和原理:
1. 启动开发服务器
Vite首先启动一个开发服务器,这个服务器通常基于Koa框架构建。这个服务器负责监听浏览器的请求,并根据请求的内容提供相应的服务。
2. 解析入口模块
当用户访问应用程序时,Vite会解析入口模块(通常是index.html)。它会分析该模块的依赖关系,并将其作为构建的起点。这个过程会涉及对HTML文件的解析,以及对其中引用的JavaScript、CSS等资源的识别。
3. 按需编译
Vite的核心特性之一是按需编译。当浏览器请求某个模块时,Vite会检查该模块是否已经被编译。如果没有,它将根据模块的类型(如.js、.vue)采取不同的编译策略。
- 对于JavaScript文件,Vite使用esbuild进行快速的原生ES模块转换。esbuild是一个极速的JavaScript打包器和压缩器,它能够在极短的时间内完成模块的编译和转换。
- 对于Vue单文件组件(
.vue文件),Vite使用@vue/compiler-sfc进行解析和编译。这个编译器专门用于处理Vue单文件组件,能够将其编译成浏览器可以直接执行的JavaScript代码。
4. 提供虚拟模块
完成编译后,Vite会将模块包裹在一个虚拟模块中,并将该模块作为一个请求的响应返回给浏览器。这个虚拟模块是一个特殊的模块,它包含了被请求的模块的代码,并且可以在浏览器中直接加载和执行。这种方式避免了传统打包工具需要将所有模块打包成一个大型文件的问题,从而提高了开发速度和效率。
5. 热模块替换(HMR)
Vite内置了热模块替换功能,这使得在开发过程中修改代码后,可以实时更新浏览器中的页面,而无需刷新整个页面。当某个模块被修改时,Vite会重新编译该模块,并通过WebSocket等通信方式将更新后的模块发送给浏览器。浏览器接收到更新后的模块后,会替换掉原来的模块,从而实现页面的实时更新。
6. 静态资源处理
除了JavaScript和Vue文件外,Vite还会对静态资源(如CSS、图片等)进行特殊处理。这些资源会被复制到构建输出目录中,并在需要时由服务器提供给浏览器。
综上所述,Vite通过启动开发服务器、解析入口模块、按需编译、提供虚拟模块、热模块替换和静态资源处理等步骤实现了即时编译。这些步骤共同协作,使得Vite能够在开发过程中提供快速、高效的编译和构建服务。
Vite实现即时编译主要依赖于其独特的设计以及对现代浏览器原生支持的ECMAScript模块(ESM)特性的充分利用。以下是Vite实现即时编译的详细解释:
1. 利用原生ESM特性
Vite直接利用现代浏览器对ESM的原生支持,避免了传统打包工具在开发阶段对模块进行打包的过程。当代码执行到模块加载时,浏览器会动态地下载并解析导入的模块,而无需等待整个项目的构建完成。这种动态加载的方式使得Vite能够实现即时编译,即只有在实际请求某个模块时,才会在服务器端进行编译,并将编译结果返回给浏览器。
2. 按需编译与缓存
Vite在服务器端按需编译模块,并在编译后将结果缓存起来。这样,当相同的模块再次被请求时,可以直接从缓存中获取编译后的结果,而无需再次进行编译。这种方式大大提高了编译速度,特别是在大型项目中,可以显著减少开发过程中的等待时间。
3. WebSocket通信与热更新
Vite启动一个WebSocket服务器,用于与客户端(浏览器)建立持久连接,实现双向通信。当开发者修改了某个模块的代码后,Vite会检测到这个变化,并重新编译该模块。然后,Vite通过WebSocket向客户端发送更新消息,告知其有模块发生了变化。客户端接收到更新消息后,会根据之前构建好的模块依赖关系图,以非阻塞的方式请求被更新的模块,并将新的模块代码插入到当前页面中,完成热更新操作。这种局部更新的方式避免了重新加载整个应用程序,从而提高了开发效率。
4. 静态文件服务器
Vite还提供了一个静态文件服务器,用于处理项目中的静态资源(如HTML、CSS、图片等)。这些资源在请求时会被直接返回给浏览器,而无需进行额外的编译或处理。
5. 编译单文件组件
对于Vue单文件组件(.vue文件),Vite使用@vue/compiler-sfc进行编译。这个编译器专门用于处理Vue单文件组件,能够将其编译成浏览器可以直接执行的JavaScript代码。编译过程中,Vite会解析组件的模板、脚本和样式部分,并将它们转换为相应的JavaScript代码和CSS样式。
6. 优化与性能提升
为了进一步提升性能,Vite还采用了多种优化措施。例如,它使用esbuild进行快速的JavaScript代码转换和压缩;它支持Tree Shaking(树摇),即只打包实际使用的代码,以减少打包后的文件大小;它还支持代码分割(Code Splitting),即将代码拆分成多个小块,以便按需加载。
综上所述,Vite通过利用现代浏览器对ESM的原生支持、按需编译与缓存、WebSocket通信与热更新、静态文件服务器、编译单文件组件以及多种优化措施实现了即时编译。这些特性共同协作,使得Vite能够在开发过程中提供快速、高效的编译和构建服务。
相关文章:
Vite构建,用NodeJS搭建一个简单的Vite服务
Vite 是一个现代的前端构建工具,由 Vue.js 作者尤雨溪创建。它主要用于开发和构建现代 JavaScript 应用,尤其是单页应用(SPA)。Vite 相比于传统的构建工具(如 Webpack)有几个显著的优势: 即时开…...
R语言机器学习论文(六):总结
文章目录 介绍参考文献介绍 本文采用R语言对来自进行数据描述、数据预处理、特征筛选和模型构建。 最后我们获得了一个能有效区分乳腺组织的随机森林预测模型,它的性能非常好,这意味着它可能拥有非常好的临床价值。 在本文中,我们利用R语言对来自美国加州大学欧文分校的B…...
python---面向对象---综合案例(4)
案例描述 实现加减乘法运算 # _*_ encoding:utf-8 _*_# 计算器, 实现一些基本的操作, 加减乘除运算, 以及打印结果操作# ------------------------------------代码1-------------------------------------- def jia(n1, n2):return n1 n2def jian(n1, n2):return n1 - n2de…...
如何参加华为欧拉考试?
华为欧拉考试主要针对的是华为欧拉(EulerOS/openEuler)操作系统的认证考试,这一认证体系旨在培养和认证具备基于欧拉操作系统进行企业级应用运行基础环境搭建、管理和调测能力的工程师以及云计算架构师。以下是对华为欧拉考试的详细介绍&…...
算法预刷题Day9:BM28 二叉树的最大深度
描述: 描述 求给定二叉树的最大深度, 深度是指树的根节点到任一叶子节点路径上节点的数量。 最大深度是所有叶子节点的深度的最大值。 (注:叶子节点是指没有子节点的节点。) 思路: 当前节点的最大高度 ma…...
exp_lr_scheduler理解
1. exp_lr_scheduler理解 这行代码定义了一个学习率调度器,用于动态调整训练过程中优化器的学习率。让我们分解并解释其含义: 1. exp_lr_scheduler 是什么? exp_lr_scheduler 是一个 学习率调度器(LR Scheduler),由 torch.optim.lr_scheduler.StepLR 创建,旨在按照预…...
Algorithm:河内之塔
1. 说明 河内之塔(Towers of Hanoi)是法国人 M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学家 Edouard Lucas 曾提及这个故事,据…...
集中管理与实时审计:构建Linux集群(1300台服务器)日志平台的最佳实践
简介 随着企业IT基础设施的不断扩大,Linux服务器的数量也日益增多,传统的单机日志管理方式已无法满足对日志数据集中管理、审计和分析的需求。尤其是在大型集群环境中,如何高效地收集、存储和分析日志成为了一项重要的技术挑战。 背景 在实…...
在Scala中Array不可变的学习
package gjhs114import scala.collection.mutable.ArrayBuffer object Arrray114 {// 不可变数组:Array// def main(args: Array[String]): Unit {1 创建不可变数组// val arr1 Array(1,2,3)//2 访问.数组名(下标)。下标是从0开始到…...
vue3+vite 批量引入组件动态使用
import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…...
设计模式——方法链or流式接口
方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用,使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 (1)每个可链接的方法都返回对象自身的引用(通常是*this)…...
JAVA OPCUA 服务端开发,客户端连接会话监听和订阅事件监听
前言 关于使用milo开源库,开发opc ua服务器,有网友咨询如何设置服务端如何监听客户端的连接或断开事件,如何监听客户端发起订阅事件的代码实现,于是我完善了这部分的空缺整理整了这篇教程,希望能解决有同样需求,但是遇到困难的网友!因为milo没有官方文档的教程且网上详…...
pytest相关总结
1.pytest -v -s -v将测试用例名称和用例中的输出进行展示,将每条用例脚本的内容逐行进行结果展示; -s 参数是为了显示用例执行层级的打印信息 pytest使用总结笔记 - fengf233 - 博客园 2....
cin/cout的性能优化和缓冲区同步问题
目录 背景导入 问题 1.1ios::sync_with_stdio(false) 1.2为什么要解除C/C IO流同步? 1.3使用场景 2.1cin和cout的绑定关系 2.2为什么要解除绑定关系? 2.3注意事项 背景导入 大家可以先看一下这段背景知识;后面我会谈谈自己的理解; 1.在C中,标准输⼊输出流…...
redisson-spring-data与Spring-Data-Redis的版本关系问题
redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-data#spring-data-redis-integration 将 Redisson 与 Spring Boot 库集成。依赖于Spring…...
Puppeteer代理认证的最佳实践和示例
在现代网络环境中,代理服务器的使用越来越普遍,尤其是在数据抓取、网页自动化测试和网络监控等领域。Puppeteer作为一个流行的Node库,它提供了高级的API来控制Chrome或Chromium浏览器。在某些情况下,我们需要通过代理服务器来执行…...
js 字符串 只显示数字
1. 使用正则表达式的match方法 原理:正则表达式\d用于匹配一个或多个数字。match方法会在字符串中查找与正则表达式匹配的部分,并返回一个包含所有匹配结果的数组。示例代码: let str "abc123def456"; let numbers str.match(/…...
STM32标准库-FLASH
FLASH模仿EEPROM STM32本身没有自带EEPROM,但是自带了FLASH存储器。 STM32F103ZET6自带 1M字节的FLASH空间,和 128K64K的SRAM空间。 STM32F4 的 SPI 功能很强大,SPI 时钟最高可以到 37.5Mhz,支持 DMA,可以配置为 SPI协…...
PowerShell:查找并关闭打开的文件
Get-SmbOpenFile 打开 Windows PowerShell 并运行 Get-SmbOpenFile | Format-List 若要仅显示特定文件共享的连接,请使用 Where-Object 运行 Get-SmbOpenFile。 Get-SmbOpenFile | Where-Object Path -eq "C:\Data\" | Format-List Get-SmbSession 显…...
【AI系统】昇腾异构计算架构 CANN
昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN(Compute Architecture for Neural Networks),这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持,旨在提供…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
raid存储技术
1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...
