前面性能调优手册
网络相关
DNS 预解析
DNS 分析也是要时间,能通过预解析的方式去事先得到网站域名对应的 IP。
<link rel="dns-prefetch" href="//baidu.com" />
缓存文件
缓存文件针对前面性能调优来说是一个非常重要的点,较好的缓存策略能够降低资源反复载入提升网页页面的总体加载速度。
一般浏览器缓存对策分两种:强缓存和商议缓存文件。
强缓存
完成强缓存能通过二种响应头完成:Expires
和Cache-Control
。强缓存表示在缓存文件期内不用要求,state code
为 200
Expires: Wed, 22 Oct 2018 08:41:00 GMT
Expires
是 HTTP / 1.0 时代的产物,表明网络资源会到Wed, 22 Oct 2018 08:41:00 GMT
后到期,必须再度要求。而且Expires
受制于本地时间,假如更改了本地时间,可能会导致缓存失效。
Cache-control: max-age=30
Cache-Control
出现于 HTTP / 1.1,优先高过Expires
。该特性表明网络资源会到 30 秒之后到期,必须再度要求。
商议缓存文件
假如缓存文件到期了,大家就可以使用商议缓存文件去解决问题。商议缓存文件必须要求,假如缓存文件合理会回到 304。
商议缓存文件必须手机客户端和服务器端一同完成,和强缓存一样,也是有二种控制方式。
Last-Modified 和 If-Modified-Since
Last-Modified
表明本地文件最终改动日期,If-Modified-Since
会把Last-Modified
数值发给网络服务器,了解网络服务器在这个日过后网络资源是否存在升级,有升级的话就会将一个新的网络资源推送回家。
如果在当地开启缓存,就容易出现Last-Modified
被改动,因此在 HTTP / 1.1 出现ETag
。
ETag 和 If-None-Match
ETag
类似文档指纹识别,If-None-Match
会把现阶段ETag
发给网络服务器,了解该网络资源ETag
是不是变化,有变化得话就把一个新的网络资源推送回家。而且ETag
优先比Last-Modified
高。
选择适合自己的缓存策略
对于大多数的画面都可以用强缓存相互配合商议缓存文件处理,但在一些特殊的地区很有可能应该选择特殊缓存策略
- 对于有些不用缓存文件资源,可以用
Cache-control: no-store
,表明该网络资源不用缓存文件 - 针对经常变化的网络资源,可以用
Cache-Control: no-cache
并协助ETag
应用,表明该网络资源已经被缓存文件,可是每次都是发送数据了解网络资源是不是升级。 - 针对编码文档而言,通常使用
Cache-Control: max-age=31536000
并协助对策缓存文件应用,再对文件进行指纹识别解决,一旦文件夹名称变化就会马上免费下载一个新的文档。
应用 HTTP / 2.0
由于电脑浏览器会出现并发请求限定,在 HTTP / 1.1 时期,每一个要求都要建立与断掉,耗费了几个 RTT 时长,而且由于 TCP 慢启动的主要原因,载入结构复杂文件会需要更多时长。
在 HTTP / 2.0 中引进了时分复用,可以让好几个要求应用同一个 TCP 连接,很大的推动了网页的加载速度。而且还提供了 Header 缩小,进一步的降低了请求的数据大小。
预加载
在设计中,可能碰到这种情况。有一些网络资源不用立刻使用,可是期待尽快获得,此刻就可以使用预加载。
预加载其实就是声明式的fetch
,强制性电脑浏览器要求网络资源,并且不会堵塞onload
事情,可以用下列编码打开预加载
<link rel="preload" href="http://example.com" />
预加载能够一定程度上减少首屏的加载时间,因为能将一些不受影响首屏但关键文件推迟载入,唯一缺点是兼容模式不太好。
预渲染
能通过预渲染将下载的文件事先在平台上3D渲染,可以用下列编码打开预渲染
<link rel="prerender" href="http://example.com" />
预渲染尽管能提高界面的加载速度,可是要保证该网页页面百分之百能被客户在接下来开启,不然就浪费网络资源去3D渲染
提升3D渲染全过程
懒实行
懒实行就是把一些逻辑性延迟时间到使用中再测算。该方法可用作首屏提升,对于有些用时逻辑性并不一定在首屏就使用的,就可以使用懒实行。懒实行必须唤起,一般能通过计时器或是事件启用来唤起。
懒加载
懒加载便是把不关键性的网络资源推迟载入。
懒加载的基本原理便是只载入自定地区(一般是可视性地区,但也能是将进入可视性地区)内必须载入的东西了。相对于照片而言,先设置图片标签的src
特性为一张团块图,将真实的图片网络资源放进一个自定义属性中,当进到自定地区时,就把自定义属性替换为src
特性,那样照片都会去下载资源,完成了图片懒加载。
懒加载不但可以用以照片,也可以用在其它网络资源上。例如进到可视性地区才播放影片这些。
文档提升
图片优化
测算图片尺寸
针对一张 100 _ 100 像素的照片而言,图象上面有 10000 个像素数,假如每一个像素的值是 RGBA 存放得话,那样换句话说每一个清晰度有 4 个安全通道,每一个安全通道 1 个字节数(8 位 = 1 个字节数),所以这类图片尺寸大概为 39KB(10000 _ 1 * 4 / 1024)。
但在具体工程中,一张图片很有可能并不一定应用这么多色调去表明,我们通过降低每一个像素的调色盘来相对应变小图片的大小。
了解到了怎么计算图片尺寸的基础知识,那对于怎样优化图片,相信大家已有 2 个构思了:
- 降低像素数
- 降低每一个像素可以标注的色调
图片加载提升
-
无需照片。有些时候会用到许多装饰类照片,实际上这种装饰照片可以用 CSS 去取代。
-
相对于手机端而言,屏幕宽度就这么点,完全没必要去载入原照消耗网络带宽。一般照片会用 CDN 载入,能够算出兼容显示屏的宽度,然后再去要求相对应裁切漂亮的图片。
-
小图片应用 base64 文件格式
-
将好几个图标文件整合到一张图片中(雪碧图)
-
选择适合的图片的格式:
- 针对可以表明 WebP 文件格式浏览器最好使用 WebP 文件格式。由于 WebP 文件格式具有更好的图像信息压缩算法,能够带来更小的图片容积,并且有着人眼鉴别没有区别的图像清晰度,缺点是兼容模式并不好
- 小图片应用 PNG,其实对绝大多数标志这种照片,彻底可以用 SVG 取代
- 相片应用 JPEG
其他资料提升
- CSS 文档放到
head
中 - 服务器端打开压缩照片作用
- 将
script
标识放到body
底端,由于 JS 文档实行会堵塞3D渲染。当然你也可以把script
标识放到随意部位随后再加上defer
,表明该文件会并行处理免费下载,但是也会放进 HTML 分析结束后顺序执行。针对没有依靠的 JS 文档能够再加上async
,表明载入和3D渲染后面文本文档元素全过程将与 JS 文件信息载入和执行并行处理混乱开展。 - 实行 JS 编码太长会卡死3D渲染,对需要大量时间测算的代码能够考虑使用
Webworker
。Webworker
能够让我们另开一个进程执行脚本且不危害3D渲染。
CDN
静态资源最好使用 CDN 载入,因为电脑浏览器针对单独网站域名有并发请求限制,能够考虑使用好几个 CDN 网站域名。针对 CDN 载入静态资源应注意 CDN 网站域名要和域名不一样,不然每一次要求都是会携带主站 Cookie。
别的
应用 Webpack 提升新项目
- 应用 ES6 控制模块来打开 tree shaking,这个技术能够清除未使用的代码
- 优化图片,针对小图片可以用 base64 的形式写入文件中
- 依照路由器分割编码,完成按需加载
- 给装包出的文件夹名称加上hach,完成浏览器缓存文档
监管
针对程序执行不正确,一般的方法是应用window.onerror
阻拦出错。此方法能阻拦到绝大多数的具体出错信息内容,但还是有除外
- 针对跨域请求的程序执行不正确显示的是
Script error.
面对这种情况我们应该给script
标识加上crossorigin
特性 - 对于有些电脑浏览器也许不会表明调用栈信息内容,这样的事情能通过
arguments.callee.caller
做栈递归算法
针对异步代码而言,可以用catch
的形式捕捉不正确。例如Promise
可以直接使用catch
函数公式,async await
可以用try catch
不过要注意网上运作的代码全是缩小完的,必须在装包时形成 sourceMap 文档有利于 debug。
针对捕捉错误必须上传到云服务器,一般能通过img
标签的src
进行一个要求。
面试问题
如何渲染几万元条数据信息并不是卡死页面
这题研究了怎样在没有卡死网页页面的情形下3D渲染数据信息,换句话说不可以一次性将几万元条都3D渲染出去,而是要一次3D渲染一部分 DOM,那就可以根据requestAnimationFrame
来每 16 ms 更新一次。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<ul>
控制
</ul>
<script>
setTimeout(() => {
// 插进十万条数据信息
const total = 100000
// 一次插进 20 条,如果你觉得特性不好就降低
const once = 20
// 3D渲染数据信息一共必须几回
const loopCount = total / once
let countOfRender = 0
let ul = document.querySelector('ul')
function add() {
// 提升特性,插进不会产生逆流
const fragment = document.createDocumentFragment()
for (let i = 0; i < once; i ) {
const li = document.createElement('li')
li.innerText = Math.floor(Math.random() * total)
fragment.appendChild(li)
}
ul.appendChild(fragment)
countOfRender = 1
loop()
}
function loop() {
if (countOfRender < loopCount) {
window.requestAnimationFrame(add)
}
}
loop()
}, 0)
</script>
</body>
</html>