写点什么

浅析 Web 前端性能优化

  • 2020-02-14
  • 本文字数:2699 字

    阅读完需:约 9 分钟

浅析Web前端性能优化

什么是 WEB 前端呢?就是用户电脑的浏览器,所做的一切事情。我们来看看用户访问网站,浏览器都做了哪些事情。


输入网址 –> 解析域名 -> 请求页面 -> 解析页面并发送页面中的资源请求 -> 渲染资源 -> 输出页面 -> 监听用户操作 -> 重新渲染。


通过上面可以看出浏览器分为三部分来实现用户的使用,我们就从这三个部分来浅析如何提升 WEB 前端性能。


一、 请求


浏览器为了减少请求传输,实现了自己的缓存机制。浏览器缓存就是把一个已经请求过的 Web 资源拷贝一份副本存储在浏览器中。当再次请求相同的 URL 时,先去查看缓存,如果有本地缓存,浏览器缓存机制会根据验证机制(Etag)和过期机制(Last-Modified)进行判断是使用缓存,还是从服务器传输资源文件。具体流程如下图所示:


1506321631051056382.png


浏览器的请求有些是并发的,有些是阻塞的。图片、CSS、接口的请求是并发,JS 文件是阻塞的。请求 JS 的时候,浏览器会中断渲染进程,等待 JS 文件加载解析完毕,再重新渲染。所以要把 JS 文件放在页面的最后。


JS 也可以通过两种方式由阻塞改成并行。一种是通过创建 script 标签,插入 DOM 中;另一种是在 Script 标签中增加 async 属性。


每种浏览器对同一域名并发的数量有限制,IE6/7 是 2,IE9 是 10,其他常见的浏览器是 6,所以减少资源请求数量和使用多域名配置资源文件,能大大提高网站性能。


减少资源请求数量的方法,大致有以下几种:


1、 通过打包工具,合并资源,减少资源数量。就是开发版本是很多个资源文件,部署的时候,按类合并成几个文件来输出。在实现模块管理的同时,实现统一输出。


2、 CSS 中,使用 css sprite 减少图片请求数量。


3、 通过延迟加载技术,在用户无感知的情况下请求资源。


4、 通过服务器配置,实现一次请求,返回多个资源文件,如淘宝 CDN 那样。


除了减少请求数量,也可以使用 CDN 镜像,来减少网络节点,实现快速响应。使用了 CDN 的请求,会根据用户所处的地理位置,找寻最近的 CDN 节点,如果请求是新的,则从资源服务器拷贝到节点,然后再返回给客户端。如果请求已经存在,则直接从节点返回客户端。


通过上面我们了解的缓存机制,如果我们部署上线的时候,是需要刷新缓存的。普通缓存通过强刷就能改过来,而 CDN 缓存则需要通过改变 URL 来实现。同时我们不可能要求用户按着 Ctrl 来刷新,所以通过打包工具,在部署的时候,统一更改 URL 是最有效的方式。而不常变更的库文件,比如 echart、jquery,则不建议更改。


二、 传输


从服务器往客户端传输,可以开启 gzip 压缩来提高传输效


Gzip 有从 1-10 的十个等级。越高压缩的越小,但压缩使用的服务器硬件资源就越多。根据实践,等级为 5 的时候最均衡,此时压缩效果是 100k 可以压缩成 20k。


三、 渲染


浏览器在加载了 html 后,就会一边解析,一边根据解析出来


结果进行资源请求,并生成 DOM 树。而加载完毕的 CSS,则被渲染引擎根据生成好的 DOM 树,来生成渲染树。等所有资源解析完毕计算好 layout 后,向浏览器界面绘制。随着用户操作,JS 会修改 DOM 节点或样式,重新绘制和重新排列。重新绘制指的是绘制 DOM 节点对应的渲染节点,重新排列是指重新计算这些节点在浏览器界面的位置。很显然,重排是非常耗性能的。我们要做的是减少重排的次数。


生成 DOM 树的时候,我们可以通过减少 DOM 节点来优化性能。最初都是用 table 布局,节点深度和数量相当复杂,性能很差。同样 CSS 作为层叠样式表,层级也不可太深,不然遍历的成本很高。另外 CSS 的 expression 属性相当耗性能,能不用则不用。动画效果能用 CSS 写的就不用 JS 写,渲染引擎不一样,性能损耗也不一样。


上面说的是解析渲染的过程,我们再接着说说用户交互操作的过程。用户操作就会导致重绘和重排,重排一定会引起重绘,而重绘不一定会引起重排。到底怎样会引起重排呢?简单的定义,DOM 结构的变化,以及 DOM 样式中几何属性的变化,就会导致重排。几何属性顾名思义,就是宽、高、边框、外补丁、内补丁等俗称盒模型的属性。同时还有 offset 之类的边距属性。


重排是最耗能的,减少重排的方法有:


1、 如果需要多次改变 DOM,则先在内存中改变,最后一次性的插入到 DOM 中。


2、 同上一条,如果多次改变样式,合成一条,再插入 DOM 中。


3、 由于 position 的值为 absoute 和 fixed 时候,是脱离文档流的,操作此类 DOM 节点,不会引起整页重排。所以动画元素设置 position 使其脱离文档流。


4、 当 DOM 节点的 display 等于 none 的时候,是不会存在于渲染树的,所以如果有比较复杂的操作,先使其 display 等于 none,等待所有操作完毕后,再将 display 设成 block,这样就只重排两次。


5、 获取会导致重排的属性值时,存入变量,再次使用时就不会再次重排。获取这些属性会导致重排:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight


以上就是浏览器如何把资源变成肉眼所见的页面的,除了上述根据浏览器流程而总结出来的性能优化,我们还需要看看 javascript 作为程序,需要的优化。先来看看 javascript 的垃圾回收机制。


Javascript 的引擎会在固定的时间间隔,将不再使用的局部变量注销掉,释放其所占的内存。而闭包的存在,将使引用一直存在,无法被释放掉。全局变量的生命周期直至浏览器卸载页面才会结束。所以一般来讲,内存溢出就是由于全局变量的不释放和闭包引起。为了防止内存溢出,我们可以做的方法有:


1、 业务代码放在匿名立即执行函数里面,执行完毕会立即释放掉。


2、 少用全局变量,同时用完的变量手动注销掉。


3、 使用回调来代替闭包访问内部属性


4、 当不可避免使用闭包时,慎重的对待其中的细节。不用的时候注销掉。


5、 通过浏览器自带的工具 profiles,来检查内存活动情况。如果是波浪型的,说明正常。如果是倾斜式渐进上涨的,说明有内存不会被释放,需要检查相应的函数。


最后再说一点,函数里返回异步取的值,经常有人这么:


Var getList = function(){ $.ajax().then(function(data){
Return data;
}) };
Var users = getList();
复制代码


毫无疑问,由于函数内的返回是异步的,所以返回只能是 undefined,而不是想要的 data。于是为了实现返回 data,就把 ajax 的 async 属性设置成了 false,由异步改为同步,来获取到 data。然而最大的问题来了,同步是会中断渲染进程的,也就是请求返回的等待中,整个页面是卡死的,用户操作也不会有响应。这个问题真正的解决方案是返回 promise 对象,而不是把异步改成同步。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/143


2020-02-14 18:55905

评论

发布
暂无评论
发现更多内容

ClickHouse在自助行为分析场景的实践应用

转转技术团队

Clickhouse MPP 大数据分析 OLAP 场景实践

大数据培训前景怎样

小谷哥

美团四面:如何保障 MySQL 和 Redis 的数据一致性?

Java永远的神

Java MySQL 数据库 redis 后端

AngularJS进阶(三十四)Angular数据更新不及时问题探讨

No Silver Bullet

angular 数据更新 12月月更

IT机构哪家Java培训比较好

小谷哥

模块一 实战营作业

peter

「架构实战营」

前端培训学习后程序员的就业前景怎么样?

小谷哥

KCL v0.4.4 发布!自定义 YAML Manifests 输出以及 Python SDK!

Peefy

编程语言 Configuration Kubernetes Serverless #DevOps

泰山众筹NFT版系统开发合约部署

薇電13242772558

智能合约

极客时间运维进阶训练营第七周作业

好吃不贵

已帮助数万程序员找到工作的阿里巴巴面试参考指南到底有什么魅力?

Java全栈架构师

程序员 程序人生 后端 java面试 八股文

全面上新!阿里2023版(Java岗)面试突击手册,Github已标星37K

Java永远的神

程序员 架构 程序人生 后端 java面试

PCB制造常用的13种测试方法,你掌握了几种?

华秋PCB

测试 PCB PCB设计

Redis缓存雪崩、击穿、穿透、双写一致性、并发竞争、热点key重建优化、BigKey的优化 等解决方案

C++后台开发

redis 中间件 后端开发 C++开发 redis缓存

ZBC登录iZUMi Finance双挖池APY高达189%,极致通缩的典范

股市老人

用友降运维成本实践:OceanBase替换MySQL,实现高可用

OceanBase 数据库

数据库 oceanbase

chatGPT辣么火,你却不会注册!

程序员小毕

Java 程序员 程序员人生 后端 摸鱼

南京哪个java培训机构好?

小谷哥

鹅厂28K程序员,不会微服务,一周就被优化了?

小小怪下士

Java 程序员 面试 微服务

AngularJS进阶(三十三)书海拾贝之简介AngularJS中使用factory和service的方法

No Silver Bullet

service AngularJS 12月月更 factory

读书破万“卷”,《软件研发效能度量规范》的先进认知与开源实现

思码逸研发效能

研发效能 效能度量

大数据培训出来后就业好吗?

小谷哥

揭秘倚天实例背后的硬核实力

阿里技术

云计算 云原生

数据库日常实操优质文章分享(含Oracle、MySQL等) | 11月刊

墨天轮

MySQL 数据库 oracle 性能优化 SQL语句

百度爱番番基于图技术、流式计算的实时CDP建设实践

NebulaGraph

数据库 flink 流计算 图数据库

AngularJS进阶(三十二)书海拾贝之特殊的ng-src和ng-href

No Silver Bullet

AngularJS 12月月更 启动过程

【DBA100人】网联客CEO隋海峰:把握好职业生涯最重要的两个5年

OceanBase 数据库

数据库 oceanbase

随机方法性能差异

FunTester

软硬协同:基于倚天的视频云编码性能升级

阿里云视频云

云计算 视频云

浅析Web前端性能优化_行业深度_马宗泽_InfoQ精选文章