前端性能优化(八):性能优化问题指南

news2024/11/19 12:41:55

目录

一:从输入 URL 到页面加载显示完成都发生了什么

二:首屏加载优化

三:JavaScript 内存管理


一:从输入 URL 到页面加载显示完成都发生了什么

UI 线程会判断输入的地址地址是搜索的关键词还是访问站点的 URL

接下来 UI 线程会通知 Network 线程,让其发起网络请求

  1. 先要进行 DNS 查找,要去把域名转换成 IP 地址
  2. 建立链接过程中还要看协议,如果使 HTTPS 需要建立 TLS 连接
  3. 如果碰到 301 (永久性移走)则要重新发起请求
  4. Server 上处理请求,最后会组织成 Response 返回给前端
  5. 读到 Response 前几个字节会开始分析数据的类型,虽然我们会在 header 部分 告诉服务器Content-Type 是什么,但是这个不一定是正确的,浏览器会对此进行判断(安全检查

 前面介绍的 UI 线程 和 Network 线程 其实都属于浏览器进程 ,接下来渲染的工作会交给渲染进程去做

主线程开始进行文本解析,把文档转换成 DOM 对象

  1. 主线程在解析构造 DOM 时,为了加快速度,会进行一个 预扫描 ,先把 HTML 里的标签给扫描出来。HTML 解析器碰到 JS 会暂停文档进一步解析(因为 JS 会修改 DOM) ,可以使用 async/defer 防止 JS 阻塞 HTML 解析
  2. 主线程解析 CSS 计算样式,创建布局树并确定每一个元素的大小&位置
  3. 接下来任务交给绘画线程复合线程来做。主线程遍历布局树后会创建绘制记录,因为绘画是有顺序的,之后将页面拆分构建成 图层树,最后复合线程把图层创建一成一个 复合帧
     

二:首屏加载优化

  • Web 增量加载的特点决定了首屏性能不会完美
  • 过长的白屏影响用户体验和留存
  • 首屏(above the fold) -> 初次印象

首屏 —— 用户加载体验的 3 个关键时刻

 测量指标:

 解决方案:

资源体积太大

  • 对 HTML、CSS、JS(压缩与混淆) 进行资源压缩
  • 传输压缩启用 Gzip
  • 使用 splitChunks 进行代码拆分(将第三方库、业务逻辑、公共代码拆分出去)
  • 使用 TreeShaking 将没有用到的代码摇下去(基于 ES6 import export)
  • 利用 HTTP 2 多路复用加快资源加载
  • 合理利用缓存(Cache-Control/Expires)

首页内容太多

  • 路由、组件、图片列表进行懒加载
  • 使用预渲染或 SSR,把 HTML 内容进行提前生成减少请求传输时间
  • 把首屏最需要的 CSS 嵌入到页面 Inline CSS

加载顺序不合适

  • 使用 prefetch、preload 提高加载顺序
     

三:JavaScript 内存管理

  • 内存泄露严重影响性能
  • 高级语言 != 不需要管理内存

变量创建时自动分配内存,不使用时 “自动” 释放内存(GC)

  • 内存释放的主要问题是如何确定不再需要使用的内存
  • 所有的 GC(垃圾回收) 都是近似实现,只能通过判断变量是否还能再次访问到
var number = 123 // 给数分配内存
var string = 'myString' // 给字符串分配内存
var obj = {
  m: 1,
  n: onj2,
} // 给对象和它的属性分配内存
var a = [1, null, 'str'] // 给数组和它包含的值分配内存
function f(a) {
  return a + 3
} // 给函数分配内存

JavaScript 有相关作用域

  • 局部变量,函数执行完,没有闭包引用,就会被标记回收
  • 全局变量,直至浏览器卸载页面时释放

GC(Garbage Collection) 实现机制

  • 引用计数 —— 无法解决循环引用的问题(a 引用 b,b 引用 a,即使其他变量没有对 a 和 b 进行引用)当创建变量后,去看一下有哪些对其进行引用,一旦被引用就不能被垃圾回收
  • 标记清除 —— 会从根节点进行扫描,去看一下所有根节点是否能被访问到,如果有节点不能被访问到就会被回收掉

// b 属性始终没有用到,但是从根节点始终可以访问到 b 属性,所以 b 属性不能被回收
const object = { a: new Array(1000), b: new Array(2000) }
setInterval(() => console.log(object.a), 1000)

解决方法:

  • 避免意外的全局变量产生
function accidentalGlobal() {
  leak1 = 'leak1'
  this.leak2 = 'leak2'
}
accidentalGlobal()
window.leak1
window.leak2
  • 避免反复运行引用大量闭包
// store会持有outer的上下文
var store
function outer() {
  var largeData = new Array(1000)
  var preStore = store
  function inner() {
    if (preStore) return largeData
  }
  return function () {}
}
setInterval(function () {
  store = outer()
}, 10)
  • 避免脱离的 DOM 元素
function createElement() {
  const div = document.createElement('div')
  div.id = 'detached'
  return div
}
const detachedDiv = createElement()
document.body.appendChild(detachedDiv)
function deleteElement() {
  document.body.removeChild(document.getElementById('detached'))
}
// 虽然 DOM 删除了,但是变量还在引用
deleteElement()

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

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

相关文章

[数据结构] 详解链表(超详细)

链表可是很重要的知识,是面试时常考的知识点,这次让我们系统的学习一下吧 文章目录1. 链表的定义2. 链表的创建2.1 基础创建2.2 尾插法创建头节点2.3 头插法3. 链表的基础方法3.1 获取链表长度3.2 是否包含某个节点3.3 在任意坐标处插入节点3.4 删除第一个值为key的节点3.5 删除…

【qsort函数实现】

前言: 首先在进行讲解之前,我们先进行对函数的一些相关介绍,方便大家更好的理解它。 目录函数介绍函数实现函数介绍 第一步: 我们可以先查询知道函数的使用方法: void qsort (void* base, size_t num, size_t size,i…

二级路由器的设置上网

设置步骤 (简单记录一下) 前提条件:一级路由器网络正常,这里主要是使用 lan 口,需要确保各个 lan 口正常,我家里是移动公司的路由器,有一个 lan 端口专门给电视用的,选择它来接二级…

ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-5-01:片上资源详解

【源码、文档、软件、硬件、技术交流、技术支持,入口见文末】 【所有相关IDE、SDK和例程源码均可从群文件免费获取,免安装,解压即用】 持续更新中,欢迎关注! 前面《ZigBee 3.0实战教程-Silicon Labs EFR32EmberZnet-2…

一个无线鼠标的HID Report Desc

HID设备是USB规范定义的设备类型之一,其分类号为0x03. 关于USB设备类型定义,可参见本站:USB设备类型定义 - USB中文网 HID设备除了用于专门的输入输出设备外,有时也与其它的设备类型组合成一个复杂的设备。如对于UVC摄像头设备&a…

干货!数据智能作为先进生产力,如何助力销售效能提升?

存量竞争市场中,企业需要通过精细化运营提升客户价值与 ROI。数据智能作为先进生产力,在搜索、广告、推荐业务方面已经足够成熟,那么它是如何助力销售提升效能呢?本文将详细介绍。点击文末“阅读原文”即可观看完整版直播回放&…

中科大2007年复试机试题

中科大2007年复试机试题 文章目录中科大2007年复试机试题第一题问题描述解题思路及代码第二题问题描述解题思路及代码第三题问题描述解题思路及代码第四题问题描述解题思路及代码第一题 问题描述 编写程序,判断给定数字是否是回文数。 示例 1 输入:12…

博主的心肝宝贝

写的不错的文档 Sql(Structured Query Language)语句笔记_sky wide的博客-CSDN博客常用sql语句总结https://blog.csdn.net/qq_44652591/article/details/127545318Linux samba服务配置_sky wide的博客-CSDN博客_linux samba配置但是,注意后面公司的需求,…

Docker部署Jenkins

系列文章目录 Docker部署 registry Docker搭建 svn Docker部署 Harbor Docker 部署SQL Server 2017 Docker 安装 MS SqlServer Docker部署 Oracle12c Docker部署Jenkins Docker部署Jenkins系列文章目录前言一、启动docker,下载Jenkins镜像文件二、创建Jenkins挂载目…

fastjson 1.2.24漏洞复现

原理 fastjson由于没有对type进行安全性验证,使攻击者传入危险的类,通过rmi服务指定的攻击机上的恶意class文件,导致命令执行。 版本 1.2.24 环境准备 靶机:ubuntu,192.168.52.129 攻击机:kali&#…

数组的定义和使用

一、一维数组的定义、初始化 1. 一维数组的定义 元素类型 数组名[常量表达式]; (1)一维数组是由元素类型、数组名和长度组成的构造类型。 (2)数组名必须符合C标识符规则。 (3)常量表…

【ONE·C || 初识C语言 】

总言 C语言初步认识。 文章目录总言1、main函数的三种写法2、常见数据类型:内置类型、自定义类型2.1、内置类型总述2.2、内置类型大小计算(32/64)2.3、计算机基本存储单位3、常量、变量3.1、变量3.1.1、变量的分类:全局变量、局部变量3.1.2、变量的作用域…

XL1278-SMT无线模块介绍

XL1278-SMT无线模块简介XL1278-SMT无线模块是采用SEMTECH公司最新的LoRaTM调制技术的无线芯片,该模块除传统的GFSK调制技术外,还采用了LoRa(远程)扩频技术,具有超远距离扩频通讯,高抗干扰性和最大限度的减小…

SAP 成本组件分割价格详解

本文整理CKM3中“CV成本组件”视图下各项成本的价格取值逻辑。 SELECTTCKH3~ELEMT ”成本构成号TCKH3~EL_HV ”全部成本TCKH1~TXELE ”成本构成名称TKEVA04~WERTKOMP1 ”字段名FROM TCKH3INNER JOIN TCKH1 ON TCKH1~ELEHK TCKH3~ELEHKAND T…

JavaScript 比较 和 逻辑运算符

文章目录JavaScript 比较 和 逻辑运算符比较运算符如何使用逻辑运算符条件运算符JavaScript 比较 和 逻辑运算符 比较和逻辑运算符用于测试 true 或者 false。 比较运算符 比较运算符在逻辑语句中使用,以测定变量或值是否相等。 x5,下面的表格解释了比较…

笔记本电脑连接不上wifi怎么办?看下面4种方法

WIFI可以让我们的网络运行得更快,尤其是对于工作来说,它是不可或缺的。但是有时候,我们明明在笔记本电脑上看到WIFI,但就是连接不上,笔记本电脑连接不上wifi怎么办?方法主要有下面4个! 演示机型…

剖析valueOf方法,深入探究Integer缓存实现机制

一. 问题展现我们在面试的时候,面试官经常会给面试者洒出一些迷雾,用来迷惑面试者,这时往往就需要面试者掌握底层源码,才能对问题进行较好的回答。接下来壹哥就以Integer的缓存数组为例,通过分析其源码来教会大家该如何…

Linux串口测试例程

嵌入式Linux开发过程中,进行Linux串口测试,需要针对串口进行回环测试或者指定串口接收一定的数据或者指定串口发送一定的数据使用该测试用例很快验证硬件串口的稳定性和正确性。使用代码连接如下Linux串口测试例程,进行Linux串口测试&#xf…

爬虫逆向之字体反爬(二)、镀金的天空-字体反爬-2

趁热打铁来写字体反爬的第二篇,首先是题目 网页上显示的不是常规的数字,源码里面也是一些汉字 虽然看上去很乱,但是仔细观察还是能发现一些规律,比如:长 对应 2,思对应 1 所以这里的解题思路,也…

基于Python实现四大名著章节标注汉语拼音

起因很单纯,就是给我1年级小豆包的女儿标注三国和西游章节的汉语拼音,我女儿每天都朗读 ,结果有很多字不认识,我爱人居然让我给标记不认识的完了手动注音......我勒个去......身为程序员的我怎么能忘记用程序实现呢,特…