vue项目的性能优化

结合lighthouse查看各项数据,不断进行性能优化,可以从代码、打包、部署这三个层面来优化

代码层面

1、v-if和v-show区分使用

  • v-if(惰性的)用的条件判断,是惰性的,false的话初始不会渲染,适用于运行很少改变条件
  • v-show不管是什么初始都会渲染,用的display: none来控制隐藏,适用于频繁切换条件的

2、computed、watch和methods区分使用

  • computed:
    • 一个数据受多个数据影响
    • 数据要经过开销很大的计算(如遍历一个很大的数组并做大量计算),可以用computed的缓存特性,只有数据发生变化才会重新计算,否则直接返回缓存
  • watch:
    • 一个数据影响多个数据的
    • 数据变化时,需要执行异步或开销大的操作(比如:请求API)
  • methods:
    • 希望数据要实时更新,不需要缓存

3、v-for避免同时使用v-if(要知道优先级why)

  • v-for优先级要比v-if高,每次渲染都要先遍历进行条件判断,增加了计算成本
  • 可以在computed提前把v-if的数据项给过滤掉

优先级why:vue在编译模板时,会先检测模板中的指令,将模板解析成AST,再根据AST生成对应的render函数。它会先将v-for指令转换成一个生成Vnode的函数,并生成对应的Vnode数组,再会根据v-if的条件来决定是否渲染每个Vnode

4、v-for循环添加key(会问 什么是diff?why提高速度?)

  • 设置唯一的key,能精确找到该数据,数据改变时能较快定位到diff

diff算法目的是找出差异,最小化更新视图,发生在视图更新阶段,当数据发生变化的时候,diff就对比新旧虚拟DOM,只渲染有变化的部分。

  • 1.对比是不是同类型标签,不是同类型直接替换
  • 2.是同类型标签,就执行patchVnode方法,判断新旧vnode是否相等
  • 3.相等就直接返回,不相等就要对比新旧节点,对比原则以新节点为主,主要分为以下几种:
    • newVnode和oldeVnode都有文本节点,就用新节点换旧节点
    • new有子节点,old没有,就增new的子节点
    • new没有子节点,old有,则删
    • 都有子节点,则通过updateChildren对比子节点

why提高速度:

  • 添加唯一key让diff准确识别每个节点,在列表更新时,可以准确判断出哪些节点被添加、删除、移动
  • 有key就可以通过map直接获得值得对比的旧节点的下标
  • 如果没有key就要通过循环旧节点数组用sameVnode去判断新节点和旧节点是否值得比较,值得才返回旧节点下标
  • 很显然map查找要比循环数组快

5、用Object.freeze()冻结不需要响应式变化的数据

vue初始化时,会对数据进行劫持,将数据都转换成响应式的,但有的时候只是想单纯展示数据,就可以跳过数据劫持,大大提高初次渲染速度。

可以通过Object.freeze()将data某些数据冻结,也就是configurable设置为false,在defineReactive中会检测某个key对应的configurable是否为false,是则直接返回,不是就继续配置getter/setter。

export default {data: () => ({users: {}}),async created() {const users = await axios.get("/api/users");this.users = Object.freeze(users);}
};
  • 其他使用场景:固定配置信息、常量数据(枚举值或数据字典)
  • PS:冻结后的对象是不可变的,无法添加新的属性、删除属性,也无法修改值。要想解除对象的冻结是不可能的,因为Object.freeze是不可逆操作,想要修改对象就只能重新创建一个新对象

6、防抖和节流

防抖和节流是针对用户操作的优化。

  • 防抖就是在一段时间内只执行最后一次,主要用在搜索框实时搜索、输入验证、窗口大小调整。
  • 节流是在规定的时间内只执行一次,主要用在页面滚动加载、高频点击提交、表单重复提交。

可以自己手写实现防抖节流(一定要会 高频考点),但在vuecli脚手架中可以引用Lodash库里的防抖节流函数。

7、利用keep-alive缓存

缓存常见的组件(tab页、导航栏),避免在切换路由时重复渲染相同的组件,提高性能和用户体验

8、图片懒加载、压缩、雪碧图

8.1 图片懒加载

未出现在可视区域内的图片先不加载,等滚动到可视范围再加载,实现方法主要有以下三种:

  • IntersectionObserver专门来检测某个元素是否出现在可视窗口,出现后就设置src,再取消监听。可以将逻辑封装成可重用的指令,在懒加载的图片元素上使用该指令即可

  • 移动端可以直接在img标签添加loading=“lazy”属性,浏览器自动处理图片的懒加载

  • vue中可以安装插件vue-lazyload,通过v-lazy写到对应的元素实现

    • 插件是在main.js中引入的,不会被webpack编译,直接写相对地址是获取不到图片正确地址的

    • 设置了翻页功能,且每页都是请求的数据进行渲染的,发现其他数据都会变,但是图片不变,解决办法就在后面加个key就行

      <img v-lazy="img.src" :key="img.src" >
      

IntersectionObserver(浏览器提供的API)实现图片懒加载原理:观察图片与视窗的交叉情况,从而判断是否出现在视窗中。实现图片懒加载步骤大概:

  • 创建一个观察器对象,指定要观察的图片 以及 触发交叉状态变化时的回调函数
  • 在函数中判断是否进入视窗内部
  • 进入的话就触发回调函数,执行图片加载操作,把真实地址赋给src,再停止监听
<!-- HTML -->
<img class="lazy-load" data-src="lazy-image.jpg" alt="Lazy-loaded image">
<script>// JavaScript// 创建 IntersectionObserver 对象const observer = new IntersectionObserver((entries, observer) => {entries.forEach(entry => {if (entry.isIntersecting) { // 判断目标元素是否进入视窗内const lazyImage = entry.target;lazyImage.src = lazyImage.dataset.src; // 将真实图片地址赋给src属性observer.unobserve(lazyImage); // 停止观察该目标元素}});});// 获取所有带有 lazy-load 类的图片元素const lazyImages = document.querySelectorAll('.lazy-load');// 遍历所有图片元素,开始观察lazyImages.forEach(image => {observer.observe(image);});
</script>

8.2 图片压缩

可以在webpack.base.conf.js中url-loader设置limit大小来处理图片,小于limit的图片转换成base64格式

将图片转成base64格式的原因:

  • 减少HTTP请求:转成base64后,可以直接包含在HTML、CSS或JS文件中,而不用单独的HTTP请求,也就减少了服务器的负载
  • 增加缓存利用率:图片已经在文件中,可以利用浏览器的缓存机制,避免重复加载相同的图片资源

对于一些较大的图片可以用image-webpack-loader压缩,具体配置如下:

module.exports = {module: {rules: [{test: /\.(png|jpg|gif)$/,use: [{loader: 'url-loader',options: {limit: 8192,  // 图片小于8KB时转换为base64name: '[name].[ext]',outputPath: 'images/'  // 输出到指定目录}},{loader: 'image-webpack-loader',options: {mozjpeg: {progressive: true,quality: 65},optipng: {enabled: false,},pngquant: {quality: [0.65, 0.90],speed: 4},gifsicle: {interlaced: false,},webp: {quality: 75}}}]}]}
};

8.3 雪碧图

针对多个小图标可以利用雪碧图技术,将其合并成一张大图,减少HTTP请求次数

  • 把小图标准备好,放在同一个文件夹下

  • 用webpack插件webpack-spritesmith将其合并成一张雪碧图

  • 可以设置每个图标的样式

  • 通过background-position来显示需要的图标

9、路由懒加载

路由被访问才加载对应的组件,提高首屏显示速度

const Foo = () => import('./Foo.vue')

10、第三方插件按需引入

babel-plugin-component只引入需要的组件,减小项目体积。安装包导入依赖即可,在main.js按需引入组件

项目打包层面

1、提取公共代码

安装分析工具webpack-bundle-analyzer,会生成可视化的文件链路图,根据需求做调整。

CommonsChunkPlugin(webpack内置插件)去提取多个chunk的公共部分

2、减少ES6转换成ES5的冗余代码

babel在每个输出文件中内嵌依赖的辅助函数代码,不让这些代码重复出现,可以用babel-plugin-transform-runtime插件,减小babel编译出来的代码大小。

  • 安装包

  • 修改.babelrc配置文件

    "plugins": ["transform-runtime"
    ]
    

3、压缩和合并JS、CSS文件

使用OptimizeCssnanoPlugin插件来压缩和去重css样式文件,开启optimization.minimize来压缩js代码。

4、tree shaking

tree shaking只能处理ES6模块,消除未使用过的代码,减少文件大小。

使用生产模式,在config.js设置mode: ‘production’来启用生产模式,用usedExports: true来启用tree shaking

项目部署层面

1、开启gzip压缩

前后端都可以压缩,不管在nginx还是webpack压缩,在nginx都要开启gzip压缩,要不然浏览器加载的还是未压缩的资源。

识别gzip压缩是否开启,只需要看响应头部有没有Content-Encoding:gzip这个属性,有就表明开启了。

(1)在vue-cli初始化项目中,默认有这个配置:

  • 先安装插件,再在config/index.js文件开启即可

    build: {// 其他代码…………productionGzip: true, // false不开启gizp,true开启// 其他代码
    }
    

(2)利用插件compression-webpack-plugin来实现:

用webpack会使打包时间变长,但用这个插件会有缓存,可以相对减少打包时间。

先安装好后,在vue.config.js配置支持gzip:

// vue.config.js 配置开启gzip
const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: (config) => {const plugins=[new CompressionPlugin({algorithm: 'gzip',// 压缩格式test: new RegExp(`\\.(${['js', 'css', 'json', 'html'].join('|')})$`),// 正则匹配文件后缀threshold: 1024 * 5,// 压缩阀值超过5KB时才压缩minRatio: 0.5//压缩比例缩小50%才采用})]return {plugins}
}

(3)在nginx上开启gzip

nginx压缩会占用服务器的CPU,浏览器每次请求资源,nginx都是实时压缩资源,资源很大再加上压缩级别很高(数字越大,压缩后的大小就越小)的话,返回资源的时间就会很长。

一般是nginx和webpack都开启压缩,并且在nginx加上gzip_static on配置,gzip_static启用后,浏览器请求资源时,nginx会先检查是否有该资源名称且后缀是.gz的文件,是就直接返回该gz文件内容,这样就可以避免nginx对该资源再进行压缩,浪费服务器的CPU。

在nginx/conf/nginx.conf中配置:

http {gzip  on;gzip_min_length 1k;gzip_comp_level 5;gzip_types application/javascript image/png image/gif image/jpeg text/css text/plain;gzip_buffers 4 4k;gzip_http_version 1.1;gzip_vary on;
}

2、将静态资源部署到CDN上,加速资源加载

大概的操作:

  • 选择合适的CDN提供商,将静态资源上传到CDN中
  • 配置CDN域名,将域名和上传的静态资源关联起来
  • 在前端代码中,要把原来的链接换成CDN域名下的链接

提高访问速度的原因:

  • 就近访问:CDN会在用户最近的节点上返回资源,减少网络传输的时间
  • 分担服务器负载
  • 缓存机制:CDN可以缓存静态资源的副本
  • 并行加载:支持并行加载多个资源,提高并发性和效率

3、设置合适的缓存策略(cache-control)

通过设置HTTP响应头中cache-control字段来控制缓存策略,设置HTTP响应头expires字段(表示资源的过期时间),一般结合cache-control中的max-age使用,但expires是绝对的日期时间,max-age是相对于请求时间的秒数

  • 静态资源(img、CSS、JS):max-age和expires设置较长的缓存时间,减少服务器负载,加快页面加载速度
  • 动态信息(用户、订单信息):设置较短的max-age来实现及时更新 或 no-cache禁用缓存

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

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

相关文章

【DevOps云实践】使用Azure Pipeline部署Function App

目录 介绍1 Azure DevOps2 微软Azure3 Azure Pipelines3.1 创建流水线**3.1.2 创建流水线**3.2 创建库3.3 运行流水线当流水线成功验证编译的YAML时,将显示阶段和作业。3.4 流水线审阅3.5 检查函数应用结论推荐超级课程: Docker快速入门到精通Kubernetes入门

32、计算e

作者: Turbo时间限制: 1S章节: 循环 问题描述 : 利用公式e1 1/1! 1/2! 1/3! ... 1/n!&#xff0c;编程计算e的近似值&#xff0c;直到最后一项的绝对值小于threshold&#xff08;该项不包括在结果内&#xff09;&#xff0c;输出e的值并统计累加的项数。 输入说明 : 输…

论文阅读:机器人跑酷学习

项目开源地址&#xff1a;https://github.com/ZiwenZhuang/parkour 摘要&#xff1a; 跑酷对腿部机动性是一项巨大的挑战&#xff0c;要求机器人在复杂环境中快速克服各种障碍。现有方法可以生成多样化但盲目的机动技能&#xff0c;或者是基于视觉但专门化的技能&#xff0c;…

代码随想录笔记|C++数据结构与算法学习笔记-二叉树(一)|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

全文基于代码随想录及相关讲解视频。 文字链接&#xff1a;《代码随想录》 文章目录 二叉树的递归遍历二叉树的前序遍历C代码如下 二叉树的中序遍历二叉树的后序遍历 二叉树的迭代遍历前序遍历前序遍历C代码 右序遍历右序遍历C代码 中序遍历为什么中序遍历不同中序遍历迭代法的…

FEX-Emu在Debian/Ubuntu系统使用

FEX-Emu在Debian/Ubuntu系统使用 1. Debootstrap子系统安装&#xff08;可选&#xff09;2. Debian/Ubuntu依赖包安装3. 获取FEX-Emu源码并编译4. 根文件系统RootFS安装5. 基于 FEX-Emu 运行应用 1. Debootstrap子系统安装&#xff08;可选&#xff09; sudo apt-get install …

软考 系统架构设计师系列知识点之云原生架构设计理论与实践(2)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之云原生架构设计理论与实践&#xff08;1&#xff09; 所属章节&#xff1a; 第14章. 云原生架构设计理论与实践 第1节 云原生架构产生背景 云原生&#xff08;Cloud Native&#xff09;是近几年云计算领域炙手可热的话…

599: 拉丁方阵(python)

收藏 难度&#xff1a;一般 标签&#xff1a;暂无标签 题目描述 还是Archmager的题了&#xff0c;这次就没有那么多废话了&#xff0c;请大家构造 N*N 阶的拉丁方阵(2<N<9)&#xff0c;使方阵中的每一行和每一列中数字1到N只出现一次。如N4时&#xff1a; 1 2 3 4 2 …

蓝桥杯刷题--python-27--全球变暖-dfs-bfs

1.全球变暖 - 蓝桥云课 (lanqiao.cn) import os import sys # 请在此输入您的代码 sys.setrecursionlimit(60000) n int(input()) dao [] for _ in range(n): tmp list(input()) dao.append(tmp) dict [(1, 0), (0, 1), (-1, 0), (0, -1)] used [[0 for _ in range(n)] fo…

如何让电脑定时开机?这个方法你一定要学会

前言 前段时间小白在上班的时候&#xff0c;个人使用一台台式机和一台笔记本电脑。台式机并不是经常使用&#xff0c;但整个公司的数据中心是建立在小白所使用的那台台式机上。 如果台式机没有开机&#xff0c;同事们就没办法访问数据中心获取自己想要的资料。领导也没办法链…

macOS - 创建聚合设备、切换声卡

文章目录 声卡设备 ID 在各个电脑上不一样,但同一个声卡驱动,UID是相同的。 比如 BlackHole 的声卡 UID 为 BlackHolexch_UID,在不同电脑上设备ID 可能为 55,64… 谨慎期间,使用声卡 UID 寻找设备ID,然后再做合并。 #import <CoreAudio/CoreAudio.h> #import <Au…

C#、.NET版本、Visual Studio版本对应关系及Visual Studio老版本离线包下载地址

0、写这篇文章的目的 由于电脑的环境不同&#xff0c;对于一个老电脑找到一个适配的vscode环境十分不易。总结一下C#、.NET、Visual Studio版本的对应关系&#xff0c;及各个版本Visual Studio的下载地址供大家参考 1、C#、.NET版本、Visual Studio版本对应关系如下 2、Visua…

李国武:如何评估一家精益制造咨询公司的实施能力?

在制造业转型升级的大背景下&#xff0c;精益制造已成为企业提升竞争力、实现可持续发展的关键。然而&#xff0c;面对市场上众多的精益制造咨询公司&#xff0c;如何评估其实施能力成为了众多企业的难题。本文将从多个方面为大家揭示评估精益制造咨询公司实施能力的方法&#…

稀碎从零算法笔记Day25-LeetCode:数组中的第K个最大元素

题型&#xff1a;排序、堆 链接&#xff1a;215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode C代码 优先队列建堆 class Solution { public:int findKthLargest(vector<int>& nums, int k) {// 小根堆 根节点就是…

100个Python代码(一)

打印输出: pythonCopy code print("Hello, world!") 变量赋值: pythonCopy code x 10 基本数学运算: pythonCopy code addition 5 5 subtraction 10 - 5 multiplication 4 * 3 division 8 / 2 modulus 7 % 3 exponentiation 2 ** 3 字符串拼接: py…

MySQL数据库的索引

目录 1、索引的概念 2、索引的作用 优点 缺点 3、创建索引的原则依据 4、索引的分类和创建 ​编辑 4.1普通索引 直接创建索引 修改表方式创建索引 创建表时添加索引 删除索引 4.2唯一索引 直接创建唯一索引 修改表方式创建 创建表时指定索引 4.3主键索引&…

Lamdba表达式

Lamdba表达式 Lambda是一个匿名函数&#xff0c;我们可以将Lambda表达式理解为一段可以传递的代码&#xff08;将代码像数据一样 传递&#xff09;。使用它可以写出简洁、灵活的代码。作为一种更紧凑的代码风格&#xff0c;使java语言表达能力得到提 升。 Lambda表达式在java语…

Android Kotlin(六)协程的并发问题

书接上回&#xff1a;Android Kotlin知识汇总&#xff08;三&#xff09;Kotlin 协程 协程的并发问题 在一个协程中&#xff0c;循环创建10个子协程且单独运行各自Default线程中&#xff0c;并让每个子协程对变量 i 进行1000次自增操作。示例如下&#xff1a; fun main() …

Golang基础知识(笔记迁移)

golang 变量作用域 局部作用域&#xff1a;代码块、函数内的全局作用域&#xff1a;顶层作用域&#xff0c;代码块外的就是全局&#xff0c;如果变量名大写&#xff0c;则改变量整个程序都可以使用。 类型断言 golang的类型断言在变量后加上.(type)&#xff0c;如果类型断言…

69、FIFO缓存发送数据(先入先出)

本文件用于设备数据收发缓冲使用&#xff0c;本fifo采用申请2片内存区&#xff0c;交替使用&#xff0c;写0时1读,写1时0读&#xff0c;避免同时使用相同内存块 fifo区域采用头尾相连的方式循环覆盖&#xff0c;分别记录读和写的位置&#xff0c;相等则数据为空&#xff0c;否则…

脚本实现Ubuntu设置屏幕无人操作,自动黑屏

使用 xrandr 命令可以实现对屏幕的控制&#xff0c;包括调整分辨率、旋转屏幕以及关闭屏幕等。要实现 Ubuntu 设置屏幕在无人操作一段时间后自动黑屏&#xff0c;非待机&#xff0c;并黑屏后点击触摸屏可以唤醒屏幕&#xff0c;可以借助 xrandr 命令来实现。 首先&#xff0c;…