性能优化,让用户体验更加完美(渲染层面)

前言

上一篇我们已经围绕“网络层面”探索页面性能优化的方案,接下来本篇围绕“浏览器渲染层面”继续开展探索。正文开始前,我们思考如下问题:

  1. 浏览器渲染页面会经过哪几个关键环节?“渲染层面”的优化从哪几方面着手?
  2. “渲染层面”的性能优化方案会有哪些?

渲染关键环节

image.png

优化原则

我们了解“页面渲染关键环节”后,便可知晓影响页面渲染性能的因素主要是静态资源:HTML、CSS、JS、图片等。因此“渲染层面”的性能优化方案主要就是围绕静态资源展开探索,其方案制定可围绕下面2个原则展开:

  • 尽可能减少资源个数
  • 尽可能减少资源体积大小

优化方案

image.png

HTML 优化

1.减少文件大小(压缩、精简)

  • 压缩处理 HTML,减小HTML体积
  • 精简 HTML:
    • 尽量减少 HMTL 嵌套、iframe/table 使用(table标签比其他html标签占用更多字节,导致下载时间长,占用服务器更多的流量资源)
    • 删除多余的空格、换行符、缩进和不必要注释
    • 删除冗余标签和属性
    • ...

2.DOM 优化

  • 控制DOM大小:
    • 合理的业务逻辑拆分
    • 先加载可视区,其他延迟加载(懒加载)
  • 减少DOM操作:尽可能对DOM操作统一逻辑处理,或是使用虚拟DOM(借鉴vue/react),再插入到真实DOM(减少重排重绘)

CSS 优化

1. 减少资源请求个数

  • 合并多个 CSS 样式文件
  • 按需加载样式

2. 减少文件大小(压缩)

  • 压缩处理 CSS 文件
  • 在线压缩,例如CSS Minify
  • webpack压缩插件

3. 减少文件大小(编码优化)

  • 位置放在<head>里,尽早地进行样式解析,构建CSSOM 树
  • 简化 CSS 选择器(选择器优先级:!important > 内联 > id > class|属性|伪类 > 标签 | 伪元素)
    • 尽可能减少样式层级数(选择器嵌套)
    • 少用标签选择器,尽量选择高优先级的id/class/属性/伪类选择器代替
    • 少用通配符*,只对需要修改样式的元素进行选择
    • 关注可继承属性,避免重复定义和匹配

可继承属性

  • 所有元素可继承:visibility 和 cursor。
  • 内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction。
  • 块元素可继承:text-indent和text-align。
  • 列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。
  • 表格元素可继承:border-collapse。

总结:CSS继承特性主要是指文本方面的继承,而关于与盒模型相关的属性不支持继承。

  • 优化CSS编码风格,尽可能减少重排重绘
    • 元素显隐操作频繁,可设置 visibility: hidden,让元素占位不变,不会触发重排,仅触发重绘
    • 已知图片的宽高,样式可先设置width、height,避免图片下载后整个页面发生重排
    • 避免使用CSS表达式
    • 避免频繁设置同一div样式,可进行一次性更改
    • 动画使用绝对定位(脱离文档流)定位,避免触发重排
    • ...
  • 精简 CSS,从而减少 CSS 文件大小
    • 使用缩写语句,如margin-top/bottom,直接用margin
    • 删除不必要的单位,如0px,直接写0
    • 删除过多分号
    • 删除空格和注释
    • ...

JS 优化

1. 减少文件请求个数

  • 合并多个 JS 脚本文件
  • 首屏渲染暂不需要且体积大的脚本可进行按需加载(通过script动态创建加载)
  • 合理使用缓存
    • 业务中:
      • 非敏感固定的数据可使用本地存储 localStorage/sessionStorage/IndexedDB
      • 合理缓存 DOM 对象等
    • 构建打包(比如webpack):
      • 第三方模块缓存:hard-source-webpack-plugin、DLL 动态链接库
      • loader 开启 cache 缓存
      • ...

2. 减少文件大小

  • 压缩处理:在线压缩/Webpack插件(uglify/gzip)
  • 构建打包减小bundle体积
    • 开启 TreeShaking,剔除 Dead Code
    • 剥离第三方依赖,webpack配置externals
    • 提取公共模块:webpack4.x+ 配置 optimization.splitChunks(相当于webpack旧版本的CommonsChunkPlugin)

3. 编码优化

加载时
  • 位置放<body>底部,让JS不阻塞HTML和CSS的解析
  • 合理选择加载模式(减少重排重绘)
// 1. 正常模式
<script src="index.js"></script>
// 2. async 模式(异步执行)
<script async src="index.js"></script>
// 3. defer 模式(延迟执行)
<script defer src="index.js"></script>

一般当我们的脚本与 DOM 元素和其它脚本之间的依赖关系不强时,我们会选用 async;当脚本依赖于 DOM 元素时,我们会选用 defer。(合理选择 script 加载模式,可以有效地提升性能)

运行时
  • DOM 操作优化
    • 合并多次 DOM 操作,批量执行,减少重排重绘
    • 大数据量渲染优化:分页加载/虚拟列表 virtualList
  • 函数优化
    • 获取 DOM 元素,尽量使用id选择器
    • 尽量避免使用 eval
    • 使用事件节流/防抖函数
    • 使用事件委托
  • JS动画优化
    • 避免添加大量的 JS 动画
    • 简单动画尽量使用 CSS3 动画
    • 复杂动画尽量使用 Canvas 动画
    • 合理使用 requestAnimationFrame 动画代替 setTimeout、setInterval

    requestAnimationFrame 按照浏览器的刷新率(60Hz左右)来调动动画帧,从而实现更加流畅和高性能的动画效果。

  • 执行优化
    • 合理拆分执行任务
    • 大数据计算,可使用 ​​​​​​​Web Worker开启独立于主线程的并行计算
  • ...

图片优化

1.减少图片网络请求

  • 雪碧图CSS sprite

    image.png

  • 小图标使用web font字体代替
  • 小体积图片使用base64编码

    image.png

  • 阴影、简单动画图效可用CSS3代替
  • 图片懒加载/预加载

2.减小图片大小

  • 图片压缩,可选择如下方式:
    • 在线压缩:​​​​​​​tinypng、tinyjpg
    • 插件压缩:
      • 压缩png:node-pngquant-native(可压缩50-80%左右)
      • 压缩jpg:jpegtran(可压缩10%左右)
      • 压缩gif:gifsicle

3.合理使用图片格式

简介和特性是否支持透明支持颜色种数压缩方式浏览器兼容性适用场景
jpg- 最常见、应用最广泛的图片格式
- 体积一般,通常小于 png, gif 等格式
不支持透明约1600万种颜色有损压缩几乎所有浏览器都支持呈现色彩丰富的图片,比如大背景图、轮播图或Banner图等
png8- 一种无损压缩的高保真的图片格式
- 8位的png,体积较大
支持透明256种(2^8)无损压缩几乎所有浏览器都支持呈现小图片,比如小Logo、颜色简单对比强烈小图标
png24- 一种无损压缩的高保真的图片格式
- 24位的png,体积较大
不支持透明约1600万种颜色无损压缩几乎所有浏览器都支持呈现颜色较多的图片,比如背景图
png32- 一种无损压缩的高保真的图片格式
- 32位的png,体积大
支持半透明(8位透明通道)2^32种无损压缩几乎所有浏览器都支持呈现色彩丰富高清图片,比如海报
svg- 矢量图,任意缩放不影响清晰度
- 体积视内容而定
支持设置透明度RGB/RGBA/十六进制设置颜色支持有损和无损压缩Chrome 4 (2010年1月发布)以上版本支持
caniuse.com/svg
适用任意缩放不失真的场景
gif- 支持动态图片
- 压缩率较高
- 体积较小
支持透明256种(2^8)无损压缩Chrome 58(2017年6月发布)以上版本支持
caniuse.com/gif
适用于色彩较少的动图
webp- 支持动态图片
- 压缩率较高
- 体积较小
支持透明约1600万种颜色有损和无损压缩Chrome 32(2014年1月发布)以上版本支持,兼容性不太好
caniuse.com/webp
兼容性要求不高的多种图片格式场景

4.图片加载优化

  • 懒加载

图片列表一般采用懒加载进行按需加载,滚屏时当图片已将出现在可视区域的时候进行加载。(有效地减轻服务器批量加载图片的压力)

let imgList = [...document.querySelectorAll('img')];
let len = imgList.length;const lazyLoad = (function(){let count = 0;return function() {let deleteIndexList = [];imgList.forEach((img,index)=> {let rec = img.getBoundingClientRect();if(rec.top < window.innerHeight) {// 元素出现在可视区(window.innerHeight:可视窗口的高度)img.src = img.dataset.src; // 将data-src设置成图片srcdeleteIndexList.push(index);count++;if(count === len) {// 当图片都加载完,移除滚动监听事件document.removeEventListener('scroll', lazyLoad)}}})imgList = imgList.filter((img, index)=> !deleteIndexList.includes(index))}
})()// 节流函数
const throttle = function(fn, timing = 500) {let prev = 0return function() {let now = +new Date();if(now - prev > timing) {prev = now;fn.apply(this, arguments)}}
}
// 滚动监听加上节流控制
const _throttle = throttle(lazyLoad)
document.addEventListener('scroll', _throttle)
  • 预加载

预加载preload,在大图片加载完成前先加载小的loading,用于提升用户体验。(该优化思想不仅可以用于图片加载,也能用于异步请求、html标签预加载)

// 创建 img 图片元素
const myImage = (function(){let imgNode = document.createElement('img')document.body.appendChild( imgNode )return {setSrc: function(src) {imgNode.src = src}}
})()/*** 预加载*/
const preLoad = (function(){let img = new Image();img.onload = function() {myImage.setSrc( this.src )// this指向img}return {setImg: function(src) {myImage.setSrc('./img/loading.gif')img.src = src}}
})()preLoad.setImg('./img/bg_gaoqing.jpeg')
  • 渐进式加载

5.响应式图片,随窗口大小变化

  • CSS媒体查询 @media 设置响应式
.bg {/* 正常(未缩小屏幕)加载大尺寸图片 */background-image: url('img_flowers.jpg');
}
/* 当屏幕宽度小于400 */
@media screen and (max-width: 400px) {.bg {background-image: url('img_smallflower.jpg');}
}
  • srcset属性设置响应式
<picture>  <source srcset="img_smallflower.jpg" media="(max-width: 400px)"><img src="img_flowers.jpg" alt="Flowers">
</picture>

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

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

相关文章

初试Kafka

Kafka 是一个分布式流处理平台&#xff0c;通常用作消息中间件&#xff0c;它可以处理大规模的实时数据流。以下是从零开始使用 Kafka 作为消息中间件的基本教程&#xff1a; 步骤 1: 下载和安装 Kafka 访问 Apache Kafka 官方网站&#xff1a;Apache Kafka下载最新的 Kafka …

【Redis】一文掌握Redis原理及常见问题

Redis是基于内存数据库&#xff0c;操作效率高&#xff0c;提供丰富的数据结构&#xff08;Redis底层对数据结构还做了优化&#xff09;&#xff0c;可用作数据库&#xff0c;缓存&#xff0c;消息中间件等。如今广泛用于互联网大厂&#xff0c;面试必考点之一&#xff0c;本文…

2022年山东省职业院校技能大赛高职组云计算赛项试卷第三场-公有云

2022年山东省职业院校技能大赛高职组云计算赛项试卷 目录 2022年职业院校技能大赛高职组云计算赛项试卷 【赛程名称】云计算赛项第三场-公有云 【任务1】公有云服务搭建[10分] 【适用平台】华为云 【题目1】私有网络管理[0.5分] 【题目2】云实例管理[0.5分] 【题目3】数…

什么是 MVVM?

Model–View–ViewModel &#xff08;MVVM&#xff09; 是一个软件架构设计模式&#xff0c;由微软 WPF 和 Silverlight 的架构师 Ken Cooper 和 Ted Peters 开发&#xff0c;是一种简化用户界面的事件驱动编程方式。 由 John Gossman&#xff08;同样也是 WPF 和 Silverlight…

.NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布

作者&#xff1a; Jon Galloway - Principal Program Manager, .NET Community Team Mehul Harry - Product Marketing Manager, .NET, Azure Marketing 排版&#xff1a;Alan Wang .NET Conf 2023 是有史以来规模最大的 .NET 会议&#xff0c;来自全球各地的演讲者进行了 100 …

设计模式-注册模式

设计模式专栏 模式介绍模式特点应用场景注册模式和单例模式的区别代码示例Java实现注册模式Python实现注册模式 注册模式在spring中的应用 模式介绍 注册模式是一种设计模式&#xff0c;也称为注册树或注册器模式。这种模式将类的实例化和创建分离开来&#xff0c;避免在应用程…

【广州华锐互动】VR科技科普展厅平台:快速、便捷地创建出属于自己的虚拟展馆

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经在许多领域取得了显著的成果。尤其是在展馆设计领域&#xff0c;VR科技科普展厅平台已经实现了许多令人瞩目的新突破。 VR科技科普展厅平台是广州华锐互动专门为企业和机构提供虚拟展馆设计和制作的在线平台。通过这个平台&…

Flink on K8S集群搭建及StreamPark平台安装

1.环境准备 1.1 介绍 在使用 Flink&Spark 时发现从编程模型, 启动配置到运维管理都有很多可以抽象共用的地方, 目前streampark提供了一个flink一站式的流处理作业开发管理平台, 从流处理作业开发到上线全生命周期都做了支持, 是一个一站式的流出来计算平台。 未来spark开…

Git基础学习_p1

文章目录 一、前言二、Git手册学习2.1 Git介绍&前置知识2.2 Git教程2.2.1 导入新项目2.2.2 做更改2.2.3 Git追踪内容而非文件2.2.4 查看项目历史2.2.5 管理分支&#x1f53a;2.2.6 用Git来协同工作2.2.7 查看历史 三、结尾 一、前言 Git相信大部分从事软件工作的人都听说过…

ASP.NET MVC的5种AuthorizationFilter

一、IAuthorizationFilter 所有的AuthorizationFilter实现了接口IAuthorizationFilter。如下面的代码片断所示&#xff0c;IAuthorizationFilter定义了一个OnAuthorization方法用于实现授权的操作。作为该方法的参数filterContext是一个表示授权上下文的AuthorizationContext对…

从计算机内存结构到iOS

一、冯.诺伊曼结构 当前计算机都是冯.诺伊曼结构&#xff08;Von Neumann architecture&#xff09;&#xff0c;是指存储器存放程序的指令以及数据&#xff0c;在程序运行时根据需要提供给CPU使用。 冯.诺伊曼瓶颈 在目前的科技水平之下&#xff0c;CPU与存储器之间的读写速…

挑战与应对:迅软科技探讨IT企业应对数据泄密危机的智慧之路

随着信息技术的快速发展&#xff0c;软件IT行业面临着前所未有的数据安全挑战。黑客攻击、病毒传播、内部泄密等安全威胁层出不穷&#xff0c;给企业的核心资产和运营带来严重威胁。同时&#xff0c;国家对于数据安全的法律法规也日益严格&#xff0c;要求企业必须采取更加有效…

https密钥认证、上传镜像实验

一、第一台主机通过https密钥对认证 1、安装docker服务 &#xff08;1&#xff09;安装环境依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2 &#xff08;2&#xff09;设置阿里云镜像源 yum-config-manager --add-repo http://mirrors.aliyun.com/do…

ElasticSearch 数据备份参考

ElasticSearch 数据备份参考 总结&#xff1a; 规模数据建议使用Snapshot and Restore功能&#xff0c;或者用LogStash&#xff0c;小规模数据可以用 elasticdump。 官方建议&#xff1a; 在灾难中&#xff0c;快照可以防止永久数据丢失。快照生命周期管理是对集群进行定期备份…

VLAN简介

在配置交换机或者传输设备时&#xff0c;经常会提到vlan&#xff0c;这个vlan具体是啥呢&#xff1f; VLAN&#xff08;Virtual Local Area Network&#xff09;中文名为“虚拟局域网”。它是一种在物理网络上划分出逻辑网络的方法&#xff0c;将物理上的局域网在逻辑上划分为多…

设计模式——适配器模式(Adapter Pattern)

概述 适配器模式可以将一个类的接口和另一个类的接口匹配起来&#xff0c;而无须修改原来的适配者接口和抽象目标类接口。适配器模式(Adapter Pattern)&#xff1a;将一个接口转换成客户希望的另一个接口&#xff0c;使接口不兼容的那些类可以一起工作&#xff0c;其别名为包装…

分布式下有哪些好用的监控组件?

在之前的内容中&#xff0c;分析了分布式系统下的线上服务监控的常用指标&#xff0c;那么在实际开发中&#xff0c;如何收集各个监控指标呢&#xff1f;线上出现告警之后&#xff0c;又如何快速处理呢&#xff1f;本文我们就来看下这两个问题。 常用监控组件 目前分布式系统…

机器学习之降维(维度灾难和维度爆炸)

在机器学习中,降维是指通过减少数据的特征维度来简化数据表示的过程。高维数据集可能包含冗余的信息,降维的目标是保留尽可能多的有用信息,同时减少数据的维度。降维的主要优势包括提高模型的计算效率、减轻维度灾难(curse of dimensionality)的影响以及更好地可视化数据。…

MongoDB创建和查询视图(一)

目录 限制和注意事项 应用两种方式创建视图 本文整理mongodb的官方文档&#xff0c;介绍mongodb的视图创建和查询。 Mongodb中&#xff0c;允许使用两种方式来创建视图。 //使用db.createCollection()来创建视图 db.createCollection("<viewName>",{"…

Node.js版本对比

目录 1. node版本与Npm版本对照表 2. node版本与node-sass版本对照表 3. node-sass与sass-loader版本对照表 1. node版本与Npm版本对照表 以往的版本 | Node.js 下面显示最新的对应内容&#xff0c;如果需要查找历史版本&#xff0c;可以进入上面的页面查询 VersionLTSDateV8np…