学习笔记:
一、加载和执行过程中的优化点
理解浏览器端HTML、CSS、JS的加载过程,学习掌握CSS、JS加载过程中的优化点。
HTML渲染过程中的一些特点。
- 顺序执行,并发加载
- 是否阻塞
- 依赖关系
- 引入方式
顺序执行,并发加载
HTML加载是根据词法分析顺序执行的,遇到引入文件并发加载,但不同浏览器会有不同的并发上限。
是否阻塞
CSS阻塞:
- CSS阻塞页面的渲染
- CSS阻塞JS的执行,但不阻塞JS的加载
JS阻塞:
- JS阻塞页面的渲染
- JS不阻塞资源的加载(预加载)
- JS顺序执行,阻塞后续JS逻辑的执行(单线程保证依赖关系)
依赖关系
- 页面渲染依赖于CSS的加载
- JS执行顺序的依赖关系
- JS逻辑对于DOM节点的依赖关系
引入方式
- 直接引入
- defer
- async
- 异步动态引入JS
加载和执行过程中的一些优化点
- CSS样式表置顶
- 用link代替import
- JS脚本置底
- 合理使用JS的异步加载能力
二、图片的懒加载
在做web前端开发的时候,特别是一些大型的电商网站,需要加载很多图片,但浏览器并行加载资源的能力是有限的,这就需要我们在不影响用户体验的前提下解决这个问题,从而提升用户体验。图片的懒加载可以解决这个问题。
懒加载:只有进入可视区域的资源才会被加载。
图片的懒加载带来的好处
- 减少无效资源的加载(按需加载)
- 并发加载的资源过多会阻塞JS的加载,影响网站的正常使用(若图片和静态资源在一个CDN,浏览器并发度的限制会降低用户体验)
懒加载的实现原理
当图片没有进入可视区域,img的src并不是这个图片真正的src,它只是一个占位符,它真正的url被存放在img标签的data-url(自定义)属性上,因为真正的url并没有放在src,所以不会去向服务器请求响应的资源,监听scroll事件,当图片进入到可视区域,将img的src赋值为data-url,这时src的变化会触发图片的请求。(getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性)
三、图片的预加载
什么是预加载以及预加载的优点
- 预加载指的是图片等静态资源在使用之前的提前请求。
- 当资源使用到时能直接从缓存中加载,提升用户体验。
- 页面展示的依赖关系维护
- 适用于对图片实时性要求比较高的场景
预加载原理
为了提升用户体验,在预加载资源加载完返回complete事件之后才会进行最终渲染。
预加载的实现方式
方式一
使用img标签加载,设置display:none,缓存图片
<img src="http://pic26.nipic.com/1.jpg" class="image-item" style="display: none" />
方式二
使用JS对象Image, 会提前缓存图片,直接从缓存中读取
var image = new Image();
image.src = 'http://pic26.nipic.com/1.jpg';
方式三
使用XMLHttpRequest来实现。利用XMLHttpRequest对象异步请求图片资源(和AJAX一样),可能会存在跨域问题,优点是可以控制预加载的过程(有封装的接口和方法)。
var xhr;
if(XMLHttpRequest){
xhr=new XMLHttpRequest();
}else{
xhr=new ActiveXObject();
}
xhr.open("POST","http://pic26.nipic.com/1.jpg",false);
xhr.send();
xhr.onreadystatechange=function(res){
//这里的函数异步执行
if(xhr.readyState == 4 && xhr.status == 200){
console.log(res);
}else{
console.log("Request was fail: " + xhr.status);
}
};
方式四
推荐使用第三方库preload.js来处理前端预加载资源的业务,提供的api也简单易用。
// 使用preload.js库
// false决定着使用html标签的方式去加载图片,不使用的话就走XMLHttpRequest方式去加载图片
var queue = new createjs.LoadQueue(false);
queue.on("complete", handleComplete, this);
queue.loadManifest([
{ id: "myImage", src: 'http://pic26.nipic.com/20121213/6168183_004444903000_2.jpg' },
{ id: "myImage2", src: 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1069058874,714751845&fm=27&gp=0.jpg' }
])
function handleComplete() {
var image = queue.getResult("myImage");
document.body.appendChild(image);
}
---------------------
作者:写代码的我
来源:CSDN
原文:https://blog.csdn.net/ASD850861363/article/details/78698356
四、重绘与回流
负责javaScript解析的线程和负责UI渲染的线程是互斥的,频繁触发重绘与回流会导致UI频繁渲染,最终导致JS变慢。所以CSS不仅影响渲染,而且还阻塞JavaScript脚本的执行。
什么是回流
当render tree中的一部分(或全部)因为元素的大小尺寸、布局、隐藏等改变而需要重新构建render tree。这就称为回流。
当页面布局和几何属性改变时就需要回流(CSS改变时触发回流)。所以应该尽量减少触发回流的CSS的改变。
什么是重绘
当render tree中的一些元素要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局的。比如background的改变就需要重绘。
回流必将引起重绘,而重绘不一定会引起回流。
重绘、回流对应着一些CSS属性,哪些触发重绘,哪些触发回流。
触发页面的重布局,进而触发回流的属性
- 盒子模型相关属性会触发重布局
- 定位、浮动也会触发重布局
- 改变节点的内部文字结构也会触发重布局
触发回流的CSS属性有:
只触发重绘的属性
避免重绘回流的两种方法
- 避免使用引起重绘回流的CSS属性。(比如用translate代替top的改变,用opacity代替visibility的改变)。
- 将重绘、回流的影响范围限制在单独的图层内
独立图层
将频繁重绘回流的元素单独作为一个独立的图层,那么这个DOM元素的重绘回流的影响只会在这个图层中。
好处:减小了重绘回流的波及面。
坏处:大量图层重组会有很大的计算量,耗费性能。
那么,如何将DOM元素变成新的独立图层呢?
chrome创建图层的条件
- 3D或透视变换CSS属性(perspective transform)
- 使用加速视频解码的标签
- 拥有3D上下文或加速的2D上下文的<canvas节点>
- 混合插件 如flash
- 对自己的opacity做CSS动画
- 拥有加速CSS过滤器的元素(translate-3D、translatez)
- 元素拥有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己层里)
- 元素拥有一个z-index较低且包含一个复合层的兄弟元素(该元素在复合层上渲染)
重绘回流的优化点总结
- 用translate代替top的改变(减少回流)
- 用opacity代替visibility(减少重绘)
- 不要一条条的修改DOM样式,预先定义好class,然后修改DOM的className
- 把DOM离线后修改。比如,先将DOM display:none; (有一次reflow),然后再修改无数多次,将它显示出来。
- 不要把DOM节点的属性值放在循环里,当成循环变量。
- 不要使用table布局
- 动画实现速度的选择,(频繁的回流重绘,会大量消耗CPU的资源)
- 对于动画新建图层(video标签、 canvas标签、也可以通过设置:will-change:transform;)
- 启用GPU硬件加速
五、浏览器存储
多种浏览器存储方式并存,如何选择?
cookie
- 因为HTTP请求无状态,所以需要cookie去维持客户端状态
- 过期时间expire
- cookie的生成方式:
1.http response header中的set-cookie
2.JS可以通过document.cookie来读写cookie - 仅仅作为浏览器存储(大小为4KB左右,存储能力被localStorage替代)
- httponly。如果在cookie中设置了httponly属性,那么通过JS脚本将无法读到cookie信息,这样能有效防止XSS攻击。
- cookie中在相关域名下面的网络损耗。(解决办法:CDN域名和主站域名要分开)
localStorage
- HTML5专为浏览器存储设计,大小为5M左右
- 仅在客户端使用,不和服务端进行通信。
- 接口封装较好。
- 浏览器本地缓存方案。(为提升首屏渲染的用户体验) ——优化点
- API:setItem、getItem、removeItem、clear
sessionStorage
- 会话级别的浏览器存储,大小为5M左右。
- 仅在客户端使用,不和服务端进行通信。
- 接口封装较好。
- 对于表单信息的维护。(提升用户体验) ——优化点
- API:setItem、getItem、removeItem、clear
IndexedDB
- IndexedDB 是一种低级API,用于客户端存储大量结构化数据。该API使用索引来实现对该数据的高性能搜索。虽然 Web Storage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB提供了一个解决方案。
- 为应用创建离线版本
- API:get put add delete
PWA
PWA (Progressive Web Apps) 是一种 Web App 新模型,并不是具体指某一种前沿的技术或者某一个单一的知识点,我们从英文缩写来看就能看出来,这是一个渐进式的 Web App,是通过一系列新的 Web 特性,配合优秀的 UI 交互设计,逐步的增强 Web App 的用户体验。
- 可靠:在没有网络的环境中也能提供基本的页面访问,而不会出现“未连接到互联网”的页面。
- 快速:针对网页渲染及网络数据访问有较好优化。
- 融入(Engaging):应用可以被增加到手机桌面,并且和普通应用一样有全屏、推送等特性。
service worker
service worker的生命周期
Service Worker 是一个脚本,浏览器独立于当前网页,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开了一扇大门。在未来这些特性将包括推送消息,背景后台同步, geofencing(地理围栏定位),但它将推出的第一个首要特性,就是拦截和处理网络请求的能力,包括以编程方式来管理被缓存的响应。
service worker的优化
- 使用拦截和处理网络请求的能力,去实现一个离线应用。
- 使用service worker在后台运行同时能和页面通信的能力,去实现大规模的后台数据处理。,