大致分为:DNS域名解析、TCP连接、HTTP请求、处理请求返回HTTP响应、页面渲染、关闭连接
(联系博文“http相关”理解)
不合并请求有下列缺点:
文件合并存在的问题
首屏渲染问题:当请求js文件的时候,如果页面渲染只依赖a.js文件,由于文件合并,需要等待合并后的a-b-c.js文件请求回来才能继续渲染,这样就会导致页面渲染速度变慢。这种情况大多出现在现代化的前端框架,如Vue等的使用过程中;
缓存失效问题:合并后的文件a-b-c.js中只要其中一个文件(比如a.js)发生变化,那么整个合并文件都将失效,而不采用文件合并就不会出现这种情况;
使用建议:
公共库合并:将不经常发生变化的公共组件库文件进行合并;
将不同页面的js文件单独合并:比如在单页面应用SPA中,当路由跳转到具体的页面时才请求该页面需要的js文件;
方式:使用在线网站进行文件合并、使用nodejs实现文件合并、使用webpack等前端构件化工具也可以很好地实现;
针对真实图片情况,舍弃一些相对无关紧要的色彩信息。如在线压缩网站:https://tinypng.com/
将网站上用到的一些图片整合到一张单独的图片中,从而减少网站HTTP请求数量。
原理:设定整张雪碧图可示区域,将想要显示的图标定位到该处(左上角);
缺点:整合图片比较大时,一次加载比较慢。
将图片的内容内嵌到html当中,减少网站的HTTP请求数量,常用于处理小图标和背景图片。网页内联图片写法为:
<imgsrc="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA..."alt="">
浏览器上的表现形式为:
image 转 DataUrI的网址:DataUrl
缺点:浏览器不会缓存内联图片资源、兼容性较差,只支持ie8以上浏览器、超过1000kb的图片,base64编码会使图片大小增大,导致网页整体下载速度减慢
webp的优势体现在它具有更优的图像压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha透明以及动画的特性。在JPEG和PNG上的转化效果都非常优秀、稳定和统一。安卓上不存在兼容性问题,推荐安卓下使用。
在线网站将图片转换为webp:webp
像图片这样的静态文件可以存放在CDN服务器上,让CDN服务器批量地将图片转换成Webp格式;
图片进入可视区域之后再请求图片资源的方式称为图片懒加载。适用于图片很多,页面很长的业务场景,比如电商
懒加载的作用:
减少无效资源的加载
比如一个网站有十页图片,用户只查看了第一页的图片,这就没必要将十页图片全都加载出来;
并发加载的资源过多会阻塞js的加载,影响网站正常的使用
由于浏览器对某一个host name是有并发度上限的,如果图片资源所在的CDN和静态资源所在的CDN是同一个的话,过多图片的并发加载就会阻塞后续js文件的并发加载。
懒加载实现的原理:
监听onscroll事件,判断可视区域位置:
图片的加载是依赖于src路径的,首先可以为所有懒加载的静态资源添加自定义属性字段,用于存储真实的url。比如是图片的话,可以定义data-src属性存储真实的图片地址,src指向loading的图片或占位符。然后当资源进入视口的时候,才将src属性值替换成data-src中存放的真实url。
(./img2/timg.gif是图片还没加载时同一展示的一张加载图,也就是src的初始值)
//.jpg_.webp表示当浏览器支持webp时采用webp格式,否则采用jpg格式。
<img src="" class="image-item" alt="" lazyload = "true" data-src="TB27YQvbm_I8KJjy0FoXXaFnVXa_!!400677031.jpg_180x180xzq90.jpg_.webp">
懒加载实例
可以使用元素的getBoundingRect().top来判断当前位置是否在视口内,也可以使用元素距离文档顶部的距离offsetTop和scrollTop是否小于视口高度来判断:
举例:
当快要滚动到需要展示的图片时才进行图片的请求,可以看到图片上有一个lazyload的属性:
(使用插件lazyload)
预加载与懒加载正好是相反的过程:懒加载实际上是延迟加载,将我们所需的静态资源加载时间延后;而预加载是将图片等静态资源在使用之前的提前请求,这样资源在使用到时能从缓存中直接加载,从而提升用户体验;
预加载的作用:
预加载的实例
例如九宫格抽奖业务,每个奖品都有一个选中态和非选中态,实际上这是由两张图片组合而成的。由于每个奖品的选中过程都是一瞬间,这就对图片的选中态和非选中态切换效率要求很高,如果选中态的图片没有预加载的话显然是来不及的
对于九宫格中所有图片选中态的样式和对应的图片都需要进行预加载,从而让我们在抽奖的过程中,能够瞬间从缓存中读取到选中态的图片,从而不影响抽奖效果的展示。
除此之外还有网站登录或活动时需要用到的动画,这是在动画需要的每帧图片都完全预加载完之后才会进行显示的。
实战优化点:
如果我们需要使得动画或其他节点渲染的性能提高,需要做的就是减少浏览器在运行时所需要做的下列工作:
使用top属性改变正方形位置时,存在重绘和回流Layout:
而使用translate属性改变正方形位置时,并不会引起重绘和回流:
使用visibility不触发重排,但是依然重绘;
直接使用opacity既触发重绘,又触发重排(GPU底层设计如此!);
opacity配合图层使用,既不触发重绘也不触发重排;
原因:透明度的改变时,GPU在绘画时只是简单的降低之前已经画好的纹理的alpha值来达到效果,并不需要整体的重绘。不过这个前提是这个被修改opacity本身必须是一个单独的图层。
预先定义好class,然后通过修改DOM的className来添加样式;
由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次回流
因为很小的一个改动都会造成整个table的重新布局;所以尽量使用div布局;
原理为:浏览器会检测一些特定的css属性,当DOM元素拥有这些css属性的时候,浏览器就会对该DOM元素启动GPU硬件加速;比如:transform: translateZ(0)和transform: translate3d(0, 0, 0)这两个属性都可以启动硬件加速;硬件加速同样不能滥用,否则会导致图层过多,导致合并图层时消耗大量性能。
这里省略一些点…,可自行参考
1.函数防抖
概念:不断触发一个函数,在规定时间内只让最后一次生效,前面都不生效;
实现:定时器;
应用:搜索时等用户完整输入内容后再发送查询请求;
代码实现
function debounce(fn,delay){
var timer = null
// 清除上一次延时器
return function(){
clearTimeout(timer)
// 重新设置一个新的延时器
timer = setTimeout(() => {
fn.call(this)
}, delay);
}
}
使用函数防抖可以减少事件触发的次数和频率,在某些情况下可以起到优化的作用。比如:搜索框,对于核心业务非搜索的网站,一般都是等待用户完整输入内容后才发送查询请求,一次来减少服务器的压力。像百度这样的核心业务为搜索的网站,服务器性能足够强大,所以不进行函数防抖处理;
2.函数节流
概念:不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次,以此控制函数执行频率;
实现:定时器,标识;
应用:在游戏中,可以设定人物攻击动作的最快频率,无论手速多快也无法超越这一频率;
代码实现
/*
节流函数:fn:要被节流的函数,delay:规定的时间
*/
functionthrottle(fn, delay){
// 记录上一次函数出发的时间
var lastTime = 0
return function(){
// 记录当前函数触发的时间
var nowTime = new Date().getTime()
// 当当前时间减去上一次执行时间大于这个指定间隔时间才让他触发这个函数
if(nowTime - lastTime > delay){
// 绑定this指向
fn.call(this)
//同步时间
lastTime = nowTime
}
}
}
生成方式:
因此要慎用Cookie,不要在Cookie中存储重要和敏感的数据。
Cookie性能优化的方法:
将存放静态资源的CDN服务器域名与主站的域名独立开来。这样每次请求静态文件的时候就不需要携带Cookie,从而可以节省很多流量。
例子:
比如在百度进行登录的时候,请求头里面就会有Set-Cookie字段,其中的BDUSS就是标识用户登录状态的字符串:
Set-Cookie中的httponly属性表示的是禁止js脚本访问cookie,这样能够一定程度防范XSS攻击;
在Chrome调试工具的Application选项中查看Cookies信息,可以发现该Cookie已经被网站“种”到Domain:.baidu.com这个域名下了,并且该Cookie也设置了HttpOnly属性:
此后浏览器的每次请求都会在请求头Request Headers中携带这一Cookie信息。刷新页面后可以看到,请求头中携带了Cookie信息BDUSS:
这样服务器就知道这是已经登录的用户了。
但是不是所有的请求都需要携带Cookie信息,比如优酷:
可以看到请求index.css文件时也携带了Cookie,但是这是不必要的,这就会导致流量的浪费。
所以,将CDN域名和主域名独立出来;
如百度:
可以看到请求这个静态资源的url并不是.baidu.com,而是静态资源服务器CDN;并且该请求的请求头中不会携带Cookie信息:
设置和获取Cookie
设置Cookie的方式很简单,key和value值通过等号连接:
document.cookie = "userName=zhangsan"
打开Application选项查看当前Cookie,可以看到Cookie已被改变:
获取Cookie:document.cookie
备注:
Web Storage分为SessionStorage和LocalStorage专门用于客户端浏览器的本地存储,同时空间比Cookie大很多,一般支持5-10M;
浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制;
LocalStorage
设置时:
localStorage.setItem("key", "value")
获取时:
localStorage.getItem("key")
移除时:
//该方法接受一个键名作为参数,并把该键名从存储中删除。
localStorage.removeItem('key');
//调用该方法会清空存储中的所有键名
localStorage.clear();
SessionStorage
SessionStorage用于存储浏览器的会话信息,标签页关闭之后它存储的数据就会被清空,而LocalStorage的数据不会被清空,这是二者的区别:
//设置
sessionStorage.setItem("key", "value")
//获取
sessionStorage.getItem("key")
//该方法接受一个键名作为参数,并把该键名从存储中删除。
sessionStorage.removeItem('key');
//调用该方法会清空存储中的所有键名
sessionStorage.clear();