vite性能优化提升开发体验之hmr和预编译

news2025/4/9 12:11:16

一、vite中的预编译

1. 预编译概念介绍

Vite,一个由Vue.js开发者尤雨溪开发的新型前端构建工具,主要利用了现代浏览器支持的ESM(ES模块)来进行快速开发。Vite在法语中意为“快”,其中最大的亮点就是其开发服务器启动的速度,能够在几乎看不到的时间内完成启动,这主要得益于两大关键性的技术:模块热更新HMR)和预编译Pre-Bundling)。

预编译,也就是预构建(Pre-Bundling)。在传统的打包过程中(比如使用Webpack),所有的模块都会被构建到一个文件中去,这个过程就是所谓的“打包Bundling)”。在Vite中,引入了“预编译”的这么一个概念,Vite会在服务器启动时对所有的依赖进行一次性的编译,并将其缓存起来。在后续的模块导入的时候,就不需要再对这些模块进行编译,提高了加载效率。

node_modules/.vite中的文件就是vite预编译文件
在这里插入图片描述

Vite的预编译主要针对那些大型的、复杂的第三方库,对把它们转换成可以直接在浏览器运行的ES模块。这样做主要有以下优化效果:

  1. 加快了开发过程中的加载速度。因为在开发模式下,运行Vite的应用,会请求大量的小模块,但是对于一些大型的库(比如Vue、React等),如果按照模块化的方式加载明显不合理,会造成请求过多。通过预编译,Vite将这些库提前编译到一个文件里,从而减少请求的开销。
  2. 加快了构建速度。因为预编译阶段已经预先处理了依赖的模块,所以在最终打包构建的时候,只需要处理自身的源代码逻辑,无需再额外处理依赖模块,以此提高构建速度。
  3. 改善了兼容性问题。由于很多第三方模块可能包含一些现在浏览器所不支持的代码,比如JSX,通过预编译,Vite将这些代码转换成浏览器可以直接运行的ES模块,解决了兼容性问题。
  4. 更好地实现了按需加载和代码拆分。预编译将大库拆分成多个小模块,可以按需加载,无需加载整个库,从而优化了性能。

举例来说,假设一个前端项目用到了vue、vant、axios等多个库,在没有使用预编译的情况下,每次启动项目时都需要去加载和解析这些库,耗时较长。而使用了Vite的预编译功能后,这些库可以在项目启动前就已经编译完成,后续只需要引用即可,大大提高了前端项目的启动速度和运行效率。

2. 配置预编译选项

在 Vite 项目中,我们在 vite.config.js 文件中配置 optimizeDeps 选项来实现对第三方库预编译的控制。optimizeDeps 选项允许手动设置需要预构建的依赖。exclude 属性用于排除某些不需要预编译的依赖,include 属性用于添加需要预编译的依赖。

以下是一个基本的配置示例:

// vite.config.js
module.exports = {
  optimizeDeps: {
    include: ['lodash'],   // 将 lodash 加入预编译
    exclude: ['moment']   // 将 moment 移除预编译
  }
}

在上面的示例中,lodash 将会被预编译,而 moment 将不会被预编译。

注意:开发依赖和已知不需要编译的依赖会自动被 Vite 排除掉。如果遇到有问题的依赖预编译,可以使用 exclude 来手动排除。而对于 Vite 默认没有预编译,但你需要其预编译的依赖,可以使用 include 来手动添加。

3. vite和webpack目前在预编译阶段的对比

功能/框架ViteWebpack
预编译Vite 使用 esbuild 进行预编译,因为 esbuild 是用 Go 语言写的,所以预编译的速度比 webpack 快很多。但是 esbuild 的兼容性和插件系统不如 webpack 完善Webpack 使用 babel 作为默认的预处理工具,与 esbuild 相比较,速度慢很多。但是 webpack 的社区更加活跃,有很多插件可以使用,并且兼容性更好。
Tree SharkingVite使用ES模块导入进行tree shaking,可以直接消除无用代码,效率更高。更好的支持动态导入(import())和CSS导入。Webpack的tree shaking需要在生产模式下才能执行,而且不支持动态导入和CSS导入的tree shaking,可能会保留无用代码。
缓存机制Vite在开发模式下没有使用缓存,但在生产模式下使用Rollup打包时,会进行缓存以优化构建速度。Vite的缓存机制更侧重于模块的热更新,并且,支持服务器端的模块缓存。Webpack使用硬盘缓存,初次构建慢,但是再次构建会从缓存中加载模块,从而提高构建速度。但在大型项目中,如果不合理配置,缓存可能会导致内存飙升。
优点构建速度快,开发体验好,方便快捷。支持Vue 3.0、Hot Module Replacement(HMR)等新特性。提供了丰富的配置和插件系统,适合大型项目。
劣势对于大型项目,可能会出现一些隐藏的问题和兼容性问题。配置复杂,学习曲线陡峭。初次构建速度慢。

二、热模块替换hmr

1. 什么是hmr

热模块替换Hot Module Replacement,HMR)是一种机制,它使得应用在运行时能够更新各种模块,而无需进行完全刷新。例如,某些库可以针对这个API进行优化,以达到接近无刷新更改的效果。这项技术主要针对单页面应用(SPA)。

举例说明,如果我们在编写一个网页应用,并且同时运行着一个开发服务器,那么当我们修改了代码并保存后,整个页面会自动刷新以显示出新的结果。而如果使用了HMR,就无需刷新整个页面,我们改动的部分(模块)会被自动替换掉并立即显示出新的效果

应用HMR之后的好处有:

  1. 保持应用状态:传统的整页刷新会导致当前应用的状态被丢失,而HMR能够在无需刷新整个页面的情况下替换、添加或删除模块,从而能够保持应用的状态。
  2. 只更新更改的部分:当修改一个或多个代码模块,整个应用不需要全部更新,只更新被改动的模块。
  3. 开发速度:由于只替换更改的内容,所以测试新的变更变得更快。
  4. 样式调整快:如果应用的修改仅仅是 CSS/SCSS 样式,那么 HMR 就会变得非常有用。这是因为,当你调整样式的时候,无需刷新页面,调整立马生效,这对于样式调整而言是非常有利的。

注意,HMR 主要在开发环境,生产环境通常不需要开启。

2. vite中hmr的相关配置

Vite构建的项目中,默认情况下是启用了热模块替换(HMR)的。如果你需要修改HMR相关的配置,你可以在Vite的配置文件(vite.config.js)中,对server.hmr进行设置。

例如,如果你需要禁用HMR,可以在vite.config.js中这样配置:

export default {
  server: {
    hmr: false
  }
}

如果需要设置连接超时或者跳过检查脏模块,可以如下配置:

export default {
  server: {
    hmr: {
      timeout: 30000,
      overlay: false
    }
  }
}

ViteHMR能力非常强大,它不仅可以处理JavaScript模块的热替换,还能处理CSS、HTML等其他类型的模块。只要你的代码里含有HMR相关的接口,Vite就能自动完成热替换。

在大部分情况下,你并不需要手动设置HMR,Vite默认的设置已经可以满足绝大多数应用场景。如果你需要设置HMR,通常是遇到了一些特殊的情况,比如需要修改连接超时时间、需要禁用HMR等。

3. vite中hmr的执行过程

热模块替换(Hot Module Replacement,HMR)是Vite(以及其他现代前端构建工具,如Webpack)的一个重要特性,但Vite的实现方式相对更优。

在对JavaScript、Vue、React等进行HMR时,Vite会有些不同的处理方式,总的来说,有以下几个步骤:

  1. 文件改变后,Vite的开发服务器首先会通知在客户端运行的更新代码,文件已经被更新。

  2. 在客户端,Vite有一个运行时处理器,它会找到这个文件对应的模块。

  3. 查看这个模块的其他依赖或者倚赖(即这个模块被哪些模块引用),建立依赖关系图。

  4. 如果这个模块可以被更新(即符合HMR规则)则直接更新,如果不能则会通知引用它的父模块更新。

  5. 这个过程是递归的,直至找到可以进行HMR的模块,或者已经到达了应用的顶级模块,此时则会进行全量刷新。

相比WebpackVite不需要额外的代码进行热更新,因为Vite是基于ES6模块的,可以依靠浏览器原生的import语法去请求和缓存模块,使得HMR更加高效。而Webpack是基于CommonJS的,需要通过上下文去理解模块的引用关系,实现热更新则需要额外的编译输出和运行时支持。

此外,Vite对于CSS的处理也具有优势,当CSS文件更新时,Vite直接通过inject的方式在客户端更新样式,而不会影响正在运行的JavaScript代码。

4. vite和webpack中的hmr对比

项目Vite 中的 HMRWebpack 中的 HMR
定义Vite 中,HMR 是通过 ESM 在浏览器中的原生支持,无需进行额外的浏览器以下代码处理,并且具有极快的速度。Webpack 中,HMR 是一种模块热替换的功能,可以在应用程序运行过程中替换、添加、删除模块,无需进行整个页面的刷新。
速度速度比较快,因为它只需要更新修改过的部分,而不是整个应用。相对较慢,因为当文件修改时,Webpack 会重新构建并刷新整个页面。
热更新范围由于 Vite 利用原生 ESM 进行模块热更新,所以其影响范围较小,只对被修改的模块进行更新。若一个模块的值发生了改变,改变会冒泡,使得依赖这个模块的所有模块全部更新,更新范围相当大。
原理利用了 ES6 module 的系统,当文件改变时,直接只请求改变的文件并重新执行。默认会给每个模块添加热更新代码,当文件发生变化后,通过打包工具发出的文件更改信号,触发更新函数,让客户端重新加载文件。
配置复杂度Vite 的配置相对较简单,只需要简单的几步就能启用 HMR。Webpack 的配置要复杂一些,除了需要添加 HMR 插件,还需要对其进行详细的配置。
兼容性Vite 要求 Node.js 版本 12.0.0 以上,并且只支持现代浏览器,不支持 IE。Webpack 对于旧版本的浏览器兼容性更好。

三、总结

对于hmr,在Vite中,当改动一个文件时,Vite会立即使用WebSocket向浏览器推送更新,然后浏览器通过重新获取被改动的模块,替换原有的代码,从而实现了部分更新,而不必要进行页面的整体刷新。这大大提高了开发时的用户体验。

Vite中的预编译: 在传统的 SPA 打包器中,无论 JavaScript 文件的大小,文件需要被完全解析并转换为浏览器可运行的代码,这个过程可能会比较耗时。而Vite则采取了另一个策略,即预编译。
Vite 开发服务器在启动时,会预编译所有被 import 的依赖。预编译将ES6+ 语法或 TypeScript 编译为可以在浏览器中运行的 ESnext 语法,并尽可能的粗略编译,只做最小化处理(实际上只做语法编译和依赖导入的重写),所以在具有缓存的情况下,预编译是非常快的。
在第一次页面加载时,仅需要加载和解析实际需要的代码。之后的页面导航都会只加载需要的代码,并且因为服务器在内存中保留有编译代码,所以这个过程是非常快的。

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

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

相关文章

gzyj 安全处理

目录 现场操作指导 解决方案 细节验证 4.1.1.1 4.1.1.2 4.1.1.3 4.1.1.4 4.1.1.5 4.1.2.1 4.1.2.2 4.1.2.3 4.1.2.4 4.1.2.5 4.1.3.1 4.1.3.2 4.1.3.3 4.1.3.4 技术支持可以仅看第一节即可。 现场操作指导 (1) 升级vms (2) 升级 meshview (3) nm…

从推动到拉动:研发效能提升的第一性原理

导语 |随着企业业务的快速发展,产品迭代速度越来越成为企业发展制胜的关键因素。在业务迅速扩张之下,企业研发团队的规模也在不断壮大。如何有效管理研发团队,又该如何提升企业研发效能,让企业在市场竞争中立于不败之地成为了一堂…

基础写作干货分享:微信公众号8个基本写作步骤

公众号怎么写?不知道如何下手?如何写一篇出众的公众号文章?怎么写公众号内容会出爆文?当我们涉及到基础微信公众号写作时不知道怎么写SEO教程自学网教你如何下手,八个基本写作步骤学会立马搞定困难。 确定目标受众&…

提高软件测试质量 需重点关注5个方面

在软件研发管理过程中,我们往往重视开发的进度,而对软件测试关注度不高,有些项目组甚至没有软件测试人员。这样往往容易导致测试工作出现很多问题,如测试目标不明确,不断修改测试方向;测试结果不理想&#…

Android11.0 导航栏添加图标截屏

需求: 导航栏添加截屏和电源键图标,控制截屏和用于设备重启关机功能。设置中添加延时截屏和控制截屏图标显示开关。 1. 导航栏添加图标 1.1 添加布局文件和图标icon 在layout目录下添加nav_power.xml和screenshot.xml文件 frameworks/base/packages…

远程桌面-出现身份验证错误

1. 打开本地组策略编辑器,可以按winr组合键输入gpedit.msc命令打开。 2. 选择“计算机配置”--“管理模板”--“系统”--“凭据分配”,在“凭据分配”设置中选择“加密数据库修正”。 3. 在“加密数据库修正”对话框中选择“已启动”,保护级别…

Redis解决Session共享问题

文章目录 一、集群Session共享问题二、Redis存储验证码和对象三、解决状态登录刷新问题 一、集群Session共享问题 session共享问题:多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务器时导致数据丢失的问题 tomcat可以进行多台tomcat进行…

主数据管理:识别主数据

1.识别主数据的两个方法 1.1主数据特征识别法 主要评估企业全部数据中的各类主数据是否符合主数据的每个特征,如发现任何不符合主数据特征的数据,则将其剔除出主数据管理的范畴。 高价值性:主数据具备极高的业务价值。主数据描述企业最核心的…

全面了解JavaScirpt 的垃圾(garbage collection)回收机制

全面了解JavaScirpt 的垃圾(garbage collection)回收机制 一、垃圾回收机制—GC javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。 原理:垃圾收集器会定期(周期性…

超宽带(UWB)无线通信的技术特点

近年来,超宽带(UWB)无线通信成为短距离、高速无线网络最热门的物理层技术之一。 UWB的产生与发展 超宽带(UWB)有着悠久的发展历史,但在1989年之前,超宽带这一术语并不常用,在信号的带宽和频谱结构方面也没有明确的规定。1989年&am…

Django_haystack全文搜索

haystack是全文搜索的框架,支持whoosh、solr、Xapian、Elasticsearc四种全文检索引擎,点击查看官方网站。 whoosh是用纯Python编写的全文搜索引擎,虽然性能比不上sphinx、xapian、Elasticsearc等,但是无二进制包,程序…

C语言为什么是世界上最难的语言?看完你就明白了

在当前的信息技术领域,C语言在许多大型科技公司中扮演着重要角色,如谷歌、苹果和微软。这些公司不仅开发软件,还专门设计硬件,例如AMD、英传达和英特尔等公司。它们都使用C加速库来提高软件性能。 C语言之所以难以掌握&#xff0…

一个简单不报错的summernote 图片上传案例

一个简单不报错的summernote 图片上传案例 一个比较完整的summernote上传图片的案例,没有后台(上传图片网上案例太多),只有前端js.修正了网上提供的,但是有bug的代码。 这个例子,js保证不报错。亲测可用 …

windows mysql服务自动启动 错误模块名称:ntdll.dll

在windows11家庭版系统安装mysql后,偶尔有mysql服务自动启动失败的问题,大体的原因就是MySQL的启动服务不能在Windows规定的启动时间内完成准备,于是就会停止其启动程序。windows事件日志如下: 方法一 : 检查确定文件…

计算机网络完结篇(从键入网址到响应页面-->HTTP常见面试题-->TCP三次握手及挥手-->TCP超时重传等特性-->Ip地址)

1. 基础篇 从键入网址到响应页面 1. 解析URL 生成HTTP请求信息 解析URL之后,浏览器确定了Web服务器和文件名,然后就是根据信息来生成HTTP请求信息。 2. 真实地址查询 DNS DNS服务器: 在第一步解析URL获取到对应的HTTP请求信息之后&#xf…

React 之 CSS编写方式

一、概述 整个前端已经是组件化的天下,而CSS的设计就不是为组件化而生的,所以在目前组件化的框架中都在需要一种合适的CSS解决方案 在组件化中选择合适的CSS解决方案应该符合以下条件: 可以编写局部css:css具备自己的具备作用域&a…

实现一个vscode插件:打开多个vscode项目时根据.nvmrc文件自动切换nvm

开发背景与最终功能 需要维护一些老项目,同时开发新项目时,切换nvm很烦人 最终实现vscode插件:每个vscode实例打开一个项目,切换vscode实例时能自动切换版本(需要项目根目录有一个.nvmrc文件) 插件下载 …

nextjs13中cssModule设置子标签的样式

前言 最近在学习nextjs中发现,如果在cssModule文件中直接设置子标签的样式比较麻烦,最后在网上看到一种方式可以解决,方式如下。 ps: 此方式不一定最优,因为在我看来此代码耦合性太高了,看着不太舒适,因为…

保姆级指南|APP原型设计怎么做?手把手教学超详细!

在数字化产品研发过程中,原型设计扮演着至关重要的角色。不夸张的说,产品原型很大程度决定了最终产品的成功与否。随着主流产品载体的更迭和发展,原型设计也在不断的演进。也产生了网页原型设计,桌面端app原型设计,移动…

PyTorch模型创建与nn.Module

文章和代码已经归档至【Github仓库:https://github.com/timerring/dive-into-AI 】或者公众号【AIShareLab】回复 pytorch教程 也可获取。 文章目录 模型创建与nn.Modulenn.Module 总结 模型创建与nn.Module 创建网络模型通常有2个要素: 构建子模块拼接…