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

你写的js性能有多差你知道吗 | js性能优化

性能的计算⽅式

确认⾃⼰需要关注的指标
常⻅的指标有:

  1. ⻚⾯总加载时间 load
  2. ⾸屏时间
  3. ⽩屏时间

代码 尝试⽤⼀个指令, 挂载在重要元素上, 当此元素inserted就上报

各个属性所代表的含义

  1. connectStart, connectEnd
    分别代表TCP建⽴连接和连接成功的时间节点。如果浏览器没有进⾏TCP连接(⽐如使⽤持久化连接webscoket),则两者都等于domainLookupEnd;
  2. domComplete
    Html⽂档完全解析完毕的时间节点;
  3. domContentLoadedEventEnd
    代表DOMContentLoaded事件触发的时间节点:⻚⾯⽂档完全加载并解析完毕之后,会触发DOMContentLoaded事件,HTML⽂档不会等待样式⽂件,图⽚⽂件,⼦框架⻚⾯的加载(load事件可以⽤来检测HTML⻚⾯是否完全加载完毕(fully-loaded))。
  4. domContentLoadedEventStart代表DOMContentLoaded事件完成的时间节点,此刻⽤⼾可以对⻚⾯进⾏操作,也就是jQuery中的domready时间;
  5. domInteractive
    代表浏览器解析html⽂档的状态为interactive时的时间节点。domInteractive并⾮DOMReady,它早于DOMReady触发,代表html⽂档解析完毕(即dom tree创建完成)但是内嵌资源(⽐如外链css、js等)还未加载的时间点;
  6. domLoading
    代表浏览器开始解析html⽂档的时间节点。我们知道IE浏览器下的document有readyState属性,domLoading的值就等于readyState改变为loading的时间节点;
  7. domainLookupStart domainLookupEnd
    分别代表DNS查询的开始和结束时间节点。如果浏览器没有进⾏DNS查询(⽐如使⽤了cache),则两者的值都等于fetchStart;
  8. fetchStart
    是指在浏览器发起任何请求之前的时间值。在fetchStart和domainLookupStart之间,浏览器会检查当前⽂档的缓存;
  9. loadEventStart, loadEventEnd
    分别代表onload事件触发和结束的时间节点
  10. navigationStart
  11. redirectStart, redirectEnd
    如果⻚⾯是由redirect⽽来,则redirectStart和redirectEnd分别代表redirect开始和结束的时间节点;
  12. requestStart
    代表浏览器发起请求的时间节点,请求的⽅式可以是请求服务器、缓存、本地资源等;
  13. responseStart, responseEnd
    分别代表浏览器收到从服务器端(或缓存、本地资源)响应回的第⼀个字节和最后⼀个字节数据的时刻;
  14. ecureConnectionStart
    可选。如果⻚⾯使⽤HTTPS,它的值是安全连接握⼿之前的时刻。如果该属性不可⽤,则返回undefined。如果该属性可⽤,但没有使⽤HTTPS,则返回0;
  15. unloadEventStart, unloadEventEnd
    如果前⼀个⽂档和请求的⽂档是同⼀个域的,则unloadEventStart和unloadEventEnd分别代表浏览器unload前⼀个⽂档的开始和结束时间节点。否则两者都等于0;

性能优化

  1. 加速或减少HTTP请求损耗:使⽤CDN加载公⽤库,使⽤强缓存和协商缓存,⼩图⽚使⽤Base64代替,⻚⾯内跳转其他域名或请求其他域名的资源时使⽤浏览器prefetch预解析等;
  2. 延迟加载:⾮重要的库、⾮⾸屏图⽚延迟加载,SPA的组件懒加载等;
  3. 减少请求内容的体积:开启服务器Gzip压缩,JS、CSS⽂件压缩合并,减少cookies⼤⼩,SSR直接输出渲染后的HTML等;
  4. 浏览器渲染原理:优化关键渲染路径,尽可能减少阻塞渲染的JS、CSS;
  5. 优化⽤⼾等待体验:⽩屏使⽤加载进度条、菊花图、⻣架屏代替等;

本地如何查看⻚⾯性能?

chrome performance
chrome-extension的请求混杂在⻚⾯请求中,难以分析filter中填写 -scheme:chrome-extension 即可过滤掉插件请求

webpack打包分析
webpack-bundle-analyzer插件,代码:vue.config.js + package.json

如何监控性能变化?

⽇志上报 阿⾥云演⽰

pagespeed https://developers.google.com/speed/pagespeed/insights/?hl=zh-cn
数据分析 90分位 50分位 TP50、TP90和TP99等指标常⽤于系统性能监控场景,指⾼于50%、90%、99%等百分线的情况。

具体的优化⽅式

浏览器渲染原理
和渲染息息相关的主要有

  1. GUI渲染线程
    GUI渲染线程负责渲染浏览器界⾯HTML元素,当界⾯需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执⾏。
    在Javascript引擎运⾏脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被冻结了.
  2. Js引擎线程
    JS为处理⻚⾯中⽤⼾的交互,以及操作DOM树、CSS样式树来给⽤⼾呈现⼀份动态⽽丰富的交互体验和服务器逻辑的交互处理。
    GUI渲染线程与JS引擎线程互斥的,是由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界⾯(即JavaScript线程和UI线程同时运⾏),那么渲染线程前后获得的元素数据就可能不⼀致。
    当JavaScript引擎执⾏时GUI线程会被挂起,GUI更新会被保存在⼀个队列中等到引擎线程空闲时⽴即被执⾏。
    由于GUI渲染线程与JS执⾏线程是互斥的关系,当浏览器在执⾏JS程序的时候,GUI渲染线程会被保存在⼀个队列中,直到JS程序执⾏完成,才会接着执⾏。
    因此如果JS执⾏的时间过⻓,这样就会造成⻚⾯的渲染不连贯,导致⻚⾯渲染加载阻塞的感觉。
  3. tips:
    回流(reflow):当浏览器发现某个部分发⽣了点变化影响了布局,需要倒回去重新渲染。reflow 会从这个 root frame 开始递归往下,依次计算所有的结点⼏何尺⼨和位置。reflow ⼏乎是⽆法避免的。现在界⾯上流⾏的⼀些效果,⽐如树状⽬录的折叠、展开(实质上是元素的显⽰与隐藏)等,都将引起浏览器的 reflow。⿏标滑过、点击……只要这些⾏为引起了⻚⾯上某些元素的占位⾯积、定位⽅式、边距等属性的变化,都会引起它内部、周围甚⾄整个⻚⾯的重新渲染。

重绘(repaint):改变某个元素的背景⾊、⽂字颜⾊、边框颜⾊等等不影响它周围或内部布局的属性时,屏幕的⼀部分要重画,但是元素的⼏何尺⼨没有变。


渲染流程主要分为以下4步:

  1. 解析HTML⽣成DOM树 - 渲染引擎⾸先解析HTML⽂档,⽣成DOM树
  2. 构建Render树 - 接下来不管是内联式,外联式还是嵌⼊式引⼊的CSS样式会被解析⽣成CSSOM树,根据DOM树与CSSOM树⽣成另外⼀棵⽤于渲染的树-渲染树(Render tree),
  3. 布局Render树 - 然后对渲染树的每个节点进⾏布局处理,确定其在屏幕上的显⽰位置
  4. 绘制Render树 - 最后遍历渲染树并⽤UI后端层将每⼀个节点绘制出来现代浏览器总是并⾏加载资源,例如,当 HTML 解析器(HTML Parser)被脚本阻塞时,解析器虽然会停⽌构建 DOM,但仍会识别该脚本后⾯的资源,并进⾏预加载。
    同时,由于下⾯两点:
  5. CSS 被视为渲染阻塞资源(包括JS),这意味着浏览器将不会渲染任何已处理的内容,直⾄CSSOM 构建完毕,才会进⾏下⼀阶段。
  6. JavaScript 被认为是解释器阻塞资源,HTML解析会被JS阻塞,它不仅可以读取和修改 DOM 属性,还可以读取和修改 CSSOM 属性。
    所以存在阻塞的 CSS 资源时,浏览器会延迟 JavaScript 的执⾏和 DOM 构建。另外:
  7. 当浏览器遇到⼀个 script 标记时,DOM 构建将暂停,直⾄脚本完成执⾏。
  8. JavaScript 可以查询和修改 DOM 与 CSSOM。
  9. CSSOM 构建时,JavaScript 执⾏将暂停,直⾄ CSSOM 就绪。css资源和js资源的放置位置
    所以,script 标签的位置很重要。实际使⽤时,可以遵循下⾯两个原则:
  10. CSS 优先:引⼊顺序上,CSS 资源先于 JavaScript 资源。
  11. JavaScript 应尽量少影响 DOM 的构建。

js的异步执⾏

defer async

都是异步加载js资源, 但是区别是async加载完资源后会⽴即开始执⾏, ⽽defer会在整个document解析完成后执⾏其他

⼀、图⽚资源优化

  1. 懒加载
    图⽚懒加载
    tips: 如何判断元素是否在可视区域内?
    原理:默认给图⽚设置⼀个兜底图, 监听⻚⾯滚动, 判断图⽚进⼊可视区域内后, 则给图⽚设置真实的src
  2. 预加载图⽚等资源
const img = new Image();
img.src= 'xxxxxx';
<img src="http://pic26.nipic.com/20121213/6168183 0044449030002.jpg" style="display:none"/>
  1. webp, 渐进式加载

https://help.aliyun.com/document_detail/171050.html?
spm=5176.10695662.1996646101.searchclickresult.2b9b75d6NiTHLQ
https://help.aliyun.com/document_detail/44704.html?
spm=a2c4g.11186623.6.1428.4acb1ecfHEUVE6

⼆、其他静态资源加载优化

  1. quickLink
    https://github.com/GoogleChromeLabs/quicklink
  2. prefetch
    link(rel=“dns-prefetch”, href=“//www.baidu.com”)
    link(rel=“preconnect”, href=“//www.baidu.com”)
    link(rel=“preload”, as=“script”, href=xxxxx)
    link(rel=“preload”, as=“image”, href=xxxxxx)
  3. 静态资源压缩
    gzip, Brotli https://help.aliyun.com/document_detail/27127.html?spm=a2c4g.11186623.6.645.70471769PeSCe6
  4. webpack
    打包优化 https://webpack.docschina.org/configuration/optimization/
  5. 服务端渲染
    同构渲染
    pug模板渲染
  6. 动态polyfill
    为了兼容低版本浏览器, 我们⼀般会引⼊polyfill。但是@babel/polyfill这个包⾮常⼤, gzip之后都有27.7k, ⾮常影响体积.
    https://polyfill.io/v3/api/
    阿⾥云cdn: https://polyfill.alicdn.com/polyfill.min.js?features=es6,es7,es2017,es2018&flags=gated
<script src="https://polyfill.io/v3/polyfill.js?features=es5,es6,es7,es2017,es2018&flags=gated&callback=invokeMain">
function invokeMain() {
var scriptElement = document.createElement('script');scriptElement.type = 'text/javascript';scriptElement.async = true;scriptElement.src = 'xxxxxxxxx';document.body.appendChild(scriptElement);
}
  1. 不重要的资源延迟加载
    可以放到window.addEventListener(‘load’, () => {})
  2. 节流 防抖
    节流函数:当持续触发事件时,保证⼀定时间段内只调⽤⼀次事件处理函数。
    防抖函数:当持续触发事件时,⼀定时间段内没有再触发事件,事件处理函数才会执⾏⼀次,如果设定的时间到来之前,⼜⼀次触发了事件,就重新开始延时。
    函数节流不管事件触发有多频繁,都会保证在规定时间内⼀定会执⾏⼀次真正的事件处理函数
    函数防抖只是在最后⼀次事件后才触发⼀次函数。
    ⽐如在⻚⾯的⽆限加载场景下,我们需要⽤⼾在滚动⻚⾯时,每隔⼀段时间发⼀次 Ajax 请求,⽽不是在⽤⼾停下滚动⻚⾯操作时才去请求数据。这样的场景,就适合⽤节流技术来实现。
    ⽽⽐如搜索框, 输⼊结束后才发起请求, 就适合⽤防抖

相关文章:

你写的js性能有多差你知道吗 | js性能优化

性能的计算⽅式 确认⾃⼰需要关注的指标 常⻅的指标有&#xff1a; ⻚⾯总加载时间 load⾸屏时间⽩屏时间 代码 尝试⽤⼀个指令, 挂载在重要元素上, 当此元素inserted就上报 各个属性所代表的含义 connectStart, connectEnd 分别代表TCP建⽴连接和连接成功的时间节点。如果浏…...

线程的状态、状态之间的相互转换

目录 一、线程的状态 1. NEW 2. TERMINATED 3. RUNNABLE 4. TIMED_WAITING 5. BLOCKED 6. WAITING 二、线程状态转换 1. 线程状态转换简图 一、线程的状态 线程的状态一共有 6 种&#xff1a; NEW&#xff1a;安排了工作&#xff0c;还未开始行动&#xff08;调用 st…...

Java8使用Lambda表达式(流式)快速实现List转map 、分组、过滤等操作

利用java8新特性&#xff0c;可以用简洁高效的代码来实现一些数据处理。1 数据准备1.1 定义1个Fruit对象package com.wkf.workrecord.work;import org.junit.Test;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;/*** author wuKeFan* date …...

C++之深浅拷贝

一、浅拷贝 我们看下以下代码 Test.h 文件 #pragma once #include<iostream> using namespace std; class Student { public:Student(){}~Student(){if (m_Id ! nullptr){delete m_Id;m_Id nullptr;}}Student(int id, string strName){m_Id new int[id];m_strName s…...

CoreLocation的一切

Overview 概述 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pgnvehxf-1678717852996)(./blog_cover.png)] Core Location 提供的服务可以确定设备的地理位置、高度和方向&#xff0c;或者它相对于附近 iBeacon 设备的位置。 该框架使用设备上的所…...

HashMap原理

初始化 从HashMap 源码中我们可以发现&#xff0c;HashMap的初始化有一下四种方式 //HashMap默认的初始容量大小 16&#xff0c;容量必须是2的幂 static final int DEFAULT_INITIAL_CAPACITY 1 << 4; // HashMap最大容量 static final int MAXIMUM_CAPACITY 1 <&…...

STM32入门笔记(02):独立看门狗(IWDG)和窗户看门狗(WWDG)(SPL库函数版)

1.IWDG狗简介 除了始终控制器的RCC_CSR寄存器的父为标志位和备份区域中的寄存器以外&#xff0c;系统复位 将复位所有寄存器至它们的复位状态。 当发生以下任一事件时&#xff0c;产生一个系统复位&#xff1a; 1.NRST引脚上的 低 电平&#xff0c;即 外部复位&#xff1b;2…...

javaSE系列之方法与数组的使用

[TOC] javaSE系列之方法与数组的使用 方法的定义 方法类似于C语言中的"函数"。 方法的种类 这里方法分为有参方法也分为无参方法&#xff0c; 形参和实参是两个实体&#xff08;这里相当于函数的传值调用和传址调用&#xff09; 1.非静态方法&#xff1a;普通方法/…...

常用命令总结

将常用命令汇集于此&#xff0c;以便在忘记的时候查询&#xff0c;持续更新…… Git Local changes 添加名字&#xff1a; git config --global user.name "<你的名字>"添加邮件&#xff1a; git config --globa user.email "<你的邮箱>"…...

【Linux:程序地址空间--原来操作系统也喜欢画大饼】

目录 1 代码感受 2 进程地址空间 3 扩展 1 代码感受 在正式讲程序地址空间前我们先来看一段简单的代码来分析分析&#xff1a; 1 #include<iostream>2 #include<unistd.h>3 using namespace std;4 5 int g_val100;6 7 int main()8 {9 pid_t idfork();10 if(i…...

Python实现简单信号滤波实战

在有些项目中需要对信号进行滤波处理&#xff0c;尤其是在医疗的设备中如心跳、脉搏等设备的采样后进行处理。滤波的目的就是除去某些频率的信号如噪声。常见的包括有低通滤波、高通滤波、带通滤波。 低通滤波指的是去除高于某一阈值频率的信号&#xff1b;高通滤波去除低于某…...

Java(110):非对称加密RSA的使用(KeyPair生成密钥)

Java(110)&#xff1a;非对称加密RSA的使用(KeyPair生成密钥) RSA 算法是一种非对称加解密算法。服务方生成一对 RSA 密钥&#xff0c;即公钥 私钥&#xff0c;将公钥提供给调用方&#xff0c;调用方使用公钥对数据进行加密后&#xff0c;服务方根据私钥进行解密。 1、RSA生…...

(Mybatis 学习【1】)整合 Mybatis 开发流程

Mybatis 整合流程 ① 添加MyBatis的依赖 ② 创建数据库表 ③ 编写pojo实体类 ④ 编写映射文件UserMapper.xml ⑤ 编写核心文件mybatis-config.xml ⑥ 编写测试类** 编写 pojo 实体类 (设计相应的数据库&#xff09; Data AllArgsConstructor NoArgsConstructor public class…...

一文搞懂Kerberos

Kerberos一词来源于古希腊神话中的Cerberus——守护地狱之门的三头犬&#xff0c;Kerberos是为TCP/IP 网络设计的可信第三方鉴别协议&#xff0c;最初是在麻省理工学院(MIT)为Athena 项目而开发的。Kerberos服务起着可信仲裁者的作用&#xff0c;可提供安全的网络鉴别&#xff…...

Go爬虫学习笔记(三)

day3 ‍ 04&#xff5c;敏捷之道&#xff1a;大型Go项目的开发流程是怎样的&#xff1f; 瀑布模式 流程&#xff1a; 市场调研需求分析产品设计研发实现集成与测试项目交付与维护 适用场景&#xff1a; 需求在规划和设计阶段就已经确定了&#xff0c;而且在项目开发周期内&…...

CASTEP参数设置(2)

虚拟试验&#xff08;分子模拟&#xff09; 在表征材料以及材料的相关性质时&#xff0c;只要是采用已有的理论加以解释 但是通常来说&#xff0c;需要采用已有的理论来进行设计和探索&#xff0c;伴随着工业软件的发展&#xff0c;应当选用仿真技术来缩小探索范围 传统试验V…...

浅谈对Promise的理解以及在工作中的应用

浅谈对Promise的理解以及在工作中的应用Promise的概念背景知识JavaScript的同步和异步JavaScript事件循环回调函数进行异步操作解决方案&#xff1a;PromisePromise 在工作中的运用创建PromisePromise封装AJAXPromise链式操作Promise.all()Promise.race()async和await总结Promi…...

开源|快速入门和理解并模拟实现GPS户外机器人的定位与导航

户外机器人的定位导航相对于需要建图的场景来说&#xff0c;是比较简单容易实现的&#xff0c;因为可以借助第三方地图完成定位&#xff0c;并在第三方地图中完成路径规划和下发航点等操作&#xff0c;实现的难题在于如何控制机器人完成步行和转弯。 这些在不引进RTK高精度定位…...

Java多线程系列--synchronized的原理

原文网址&#xff1a;Java多线程系列--synchronized的原理_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java的synchronized的原理。 反编译出字节码 Test.java public class Test {private static Object LOCK new Object();public static int main(String[] args) {synchro…...

QEMU启动ARM64 Linux内核

目录前言前置知识virt开发板ARM处理器家族简介安装qemu-system-aarch64安装交叉编译工具交叉编译ARM64 Linux内核交叉编译ARM64 Busybox使用busybox制作initramfs使用QEMU启动ARM64 Linux内核前言 本文介绍采用 qemu 模拟ARM-64bit开发板&#xff08;针对ARM-32bit的有另一篇文…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...

ui框架-文件列表展示

ui框架-文件列表展示 介绍 UI框架的文件列表展示组件&#xff0c;可以展示文件夹&#xff0c;支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项&#xff0c;适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

Heygem50系显卡合成的视频声音杂音模糊解决方案

如果你在使用50系显卡有杂音的情况&#xff0c;可能还是官方适配问题&#xff0c;可以使用以下方案进行解决&#xff1a; 方案一&#xff1a;剪映替换音色&#xff08;简单适合普通玩家&#xff09; 使用剪映换音色即可&#xff0c;口型还是对上的&#xff0c;没有剪映vip的&…...

无头浏览器技术:Python爬虫如何精准模拟搜索点击

1. 无头浏览器技术概述 1.1 什么是无头浏览器&#xff1f; 无头浏览器是一种没有图形用户界面&#xff08;GUI&#xff09;的浏览器&#xff0c;它通过程序控制浏览器内核&#xff08;如Chromium、Firefox&#xff09;执行页面加载、JavaScript渲染、表单提交等操作。由于不渲…...