当前位置: 首页 > news >正文

Vite构建,用NodeJS搭建一个简单的Vite服务

Vite 是一个现代的前端构建工具,由 Vue.js 作者尤雨溪创建。它主要用于开发和构建现代 JavaScript 应用,尤其是单页应用(SPA)。Vite 相比于传统的构建工具(如 Webpack)有几个显著的优势:

  1. 即时开发服务器:Vite 利用原生 ES 模块(ESM)在浏览器中提供模块热更新(HMR),这使得开发体验更加快速和流畅。
  2. 按需编译:Vite 只编译和打包你当前需要的部分,而不是整个项目,这大大减少了初始构建时间。
  3. 插件系统: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}`);
});

说明

  1. 静态文件服务:这个简单的服务器会提供 dist 目录下的静态文件。
  2. 文件监听:使用 chokidar 库监听 dist 目录下的文件变化,并在控制台打印文件变化的信息。
  3. 内容类型:根据文件扩展名设置正确的 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流式接口

方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用&#xff0c;使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 &#xff08;1&#xff09;每个可链接的方法都返回对象自身的引用&#xff08;通常是*this&#xff09…...

JAVA OPCUA 服务端开发,客户端连接会话监听和订阅事件监听

前言 关于使用milo开源库,开发opc ua服务器,有网友咨询如何设置服务端如何监听客户端的连接或断开事件,如何监听客户端发起订阅事件的代码实现,于是我完善了这部分的空缺整理整了这篇教程,希望能解决有同样需求,但是遇到困难的网友!因为milo没有官方文档的教程且网上详…...

pytest相关总结

1.pytest -v -s -v将测试用例名称和用例中的输出进行展示&#xff0c;将每条用例脚本的内容逐行进行结果展示&#xff1b; -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中&#xff0c;标准输⼊输出流…...

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代理认证的最佳实践和示例

在现代网络环境中&#xff0c;代理服务器的使用越来越普遍&#xff0c;尤其是在数据抓取、网页自动化测试和网络监控等领域。Puppeteer作为一个流行的Node库&#xff0c;它提供了高级的API来控制Chrome或Chromium浏览器。在某些情况下&#xff0c;我们需要通过代理服务器来执行…...

js 字符串 只显示数字

1. 使用正则表达式的match方法 原理&#xff1a;正则表达式\d用于匹配一个或多个数字。match方法会在字符串中查找与正则表达式匹配的部分&#xff0c;并返回一个包含所有匹配结果的数组。示例代码&#xff1a; let str "abc123def456"; let numbers str.match(/…...

STM32标准库-FLASH

FLASH模仿EEPROM STM32本身没有自带EEPROM&#xff0c;但是自带了FLASH存储器。 STM32F103ZET6自带 1M字节的FLASH空间&#xff0c;和 128K64K的SRAM空间。 STM32F4 的 SPI 功能很强大&#xff0c;SPI 时钟最高可以到 37.5Mhz&#xff0c;支持 DMA&#xff0c;可以配置为 SPI协…...

PowerShell:查找并关闭打开的文件

Get-SmbOpenFile 打开 Windows PowerShell 并运行 Get-SmbOpenFile | Format-List 若要仅显示特定文件共享的连接&#xff0c;请使用 Where-Object 运行 Get-SmbOpenFile。 Get-SmbOpenFile | Where-Object Path -eq "C:\Data\" | Format-List Get-SmbSession 显…...

【AI系统】昇腾异构计算架构 CANN

昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN&#xff08;Compute Architecture for Neural Networks&#xff09;&#xff0c;这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持&#xff0c;旨在提供…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...