性能优化 让你的页面更丝滑
前言
性能优化是一个很宏大的命题,无论是是大厂还是小公司,都在为让页面更快的展现在用户面前做优化和探索,
页面性能也是检验一个前端工程师项目成果的重要指标
,所以,无论是不是要面试,常用的性能优化的手段还是要熟练掌握
。
在前面两篇文章前端工程师必看的服务器知识、追本溯源 浏览器渲染机制,详细介绍了
url从输入到页面的渲染中间的技术细节,这篇我们总结下,常用的性能优化操作
。
神图保存
减少HTTP请求
减少页面的HTTP请求数
是个起点,这是提升站点首次访问速度的重要指导原则,小字当先
。
合并脚本和样式表
合并css和js文件,合并文件大小之后,大文件gizp
之后不能超过33kb
(不是一股脑的打包成一个),文件数量要适量
。
CSS Sprites
是减少图片请求数量的首选方式。把背景图片都整合到一张图片中,然后用CSS的 background-image
和 background-position
属性来定位要显示的部分。
行内图片(Base64编码)
用 data: URL模式 来把图片嵌入页面。这样会增加HTML文件的大小,把行内图片放在(缓存的)样式表中是个好办法,而且成功避免了页面变“重”。但目前主流浏览器并不能很好地支持行内图片。
配置多个域名和CDN加速
通常浏览器对于一个域名的并发请求是有限
的,比如:有100个文件要加载,但浏览器一次只可能并发请求10个文件,这样并发多次就会耗时。因此配置多个域名能够最大限度的增加并发请求量。
但这里有个缺点就是会增加浏览器域名解析的次数,这里建议利用CDN来加载不是经常更新和修改的静态资源(图片,css库,js第三方库等等)。一个是CDN域名一般都会缓存到本地中,另一个是CDN网络请求速度是非常快的。
缓存策略
缓存资源是最立竿见影
的手段,通过在请求头设置缓存属性,下次再次访问可以直接从本地获取资源,减少了不必要的数据传输,节省带宽、减少服务器的负担,提升网站性能、加快了客户端加载网页的速度、关于强缓存和协商缓存
的内容可以看之前前端工程师必看的服务器知识。
缓存的优先级:cache-control > expires > Etag > last-modified
在第一次请求时,浏览器会检查是否有缓存设置,记入内存,下次请求,服务器判断返回304从缓存取,200会从服务器取。
cache-control
设置过期时间长度
(秒),在这个时间范围内,浏览器就会直接读取缓存,当expires和cache-control都存在时,cache-control的优先级更大
。
expires
在http头中设置一个过期时间,这个过期时间之前,浏览器请求不会发出,从缓存中读取文件,除非缓存被清空,或者强制刷新,缺陷在于服务器时间和客户端的时间可能不一致,所有http1.1
引入了cache-control来改进。
etag
服务器返回资源时,如果头部有etag,资源在下次请求时会把值自动加到请求头if-none-match
中,服务器可以对比这个值,确定资源是否发生变化,如果没有变化返回304
。
last-modified
服务器返回资源时,如果头部有last-modified
,资源请求时机会把值加入到if-modified-since
中,服务器可以对比这个值,确定资源是否发生变化返回304
。
传输加载优化
启动gzip
在nginx中配置gzip: on
我们可以先来对比下,如果我们没有开启zip压缩之前,我们的对应的文件大小,如下所示:
现在我们开启了gzip进行压缩后的文件的大小,可以看到如下所示:
并且我们查看响应头会看到gzip这样的压缩,如下所示
这种压缩比例是非常客观的,大幅度提升了页面的效率。
Keep-Alive
在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流.
Keep-Alive 在Http1.1
默认是开启的,可以在 Response Header 中可以看到 Connection: keep-alive
。
在nginx 配置中有两个比较重要的配置
keepalive_timeout 65 // 保持连接的时间,也叫超时时间,单位秒
keepalive_request 100 // 最大连接上限
浏览器请求//xx.cn/a.js-->解析域名—>HTTP连接—>服务器处理文件—>返回数据-->浏览器解析、渲染文件。Keep-Alive解决的核心问题
就在此,一定时间内,同一域名多次请求数据,只建立一次HTTP请求,其他请求可复用每一次建立的连接通道
,以达到提高请求效率的问题。一定时间是可以配置的,
HTTP1.1还是存在效率问题
- 串行的文件传输
- 连接数过多
HTTP/2对同一域名下所有请求都是基于流,也就是说同一域名不管访问多少文件,也只建立一路连接。同样Apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了60倍!
懒加载
在可视化的窗口中才去加载图片,大大提高首次的渲染速度!
原生支持加loading属性
需要浏览器支持
第三方插件
- lazyload (opens new window)
- react-lazyload(opens new window)
渲染中性能优化
上一篇中我们我们看到浏览器在渲染的时候生成了四棵树
- GUI线程和js线程是
互斥
的 - 重排和重绘很消耗性能
把样式表放在顶部,js文件放在底部
雅虎军规规定,样式表放在顶部
,js文件放在底部
,这样做的意义是为了二位爷不要打架,和谐执行。
减少重排和重绘
chrome DevTools可以检测到页面渲染的性能分析
我们用keyframes。来实现一个动画效果。
<div class="container">
<div class="ball" id="ball"></div>
</div>
@keyframes run-around {
0% {
top: 0;
left: 0;
}
25% {
top: 0;
left: 200px;
}
50% {
top: 200px;
left: 200px;
}
75% {
top: 200px;
left: 0;
}
}
用chrome DevTols检测
- Loading:网络通信和 HTML 解析
- Scripting:JavaScript 执行时间
- Rendering:样式计算和布局,即 Layout 重排
- Painting:重绘
看到浏览器一直在重排和重绘合成的循环里
我们使用transfrom替换绝对定位进行GUI加速
。
0% {
transform: translate(0, 0);
}
25% {
transform: translate(200px, 0);
}
50% {
transform: translate(200px, 200px);
}
75% {
transform: translate(0, 200px);
}
再次录制
我们可以看到鲜明的对比,直接跳过了重排和重绘的过程,大大提升了页面的性能
requestAnimationFrame
动画操作,可以使用 requestAnimationFrame
要求浏览器在下次重绘之前调用指定的回调函数更新动画,可以达到和浏览器同步刷新,以避免不必要的开销。
雅虎军规
雅虎公司制定了8个部分,35条性能优化准则,本文部分取自军规详细展开,详情可以查看`参考链接`。
页面加载性能指标
思考一个问题?,我们在进行性能优化之后,是如何来评定我们的优化手段是否满足我们的业务,是否有量化的标准来帮助我们来分析是否还有不足,精准的定位到问题
阶段(简写) | 描述 | 阶段(全称) |
---|---|---|
TTFP | 首字节时间 | Time TO Frist Byte |
FP | 首次绘制(第一个节点) | First Paint |
FCP | 首次有内容的绘制(骨架) | First Contentful Paint |
FMP | 首次有意义的绘制(包含所有元素/数据) | First Meaningful |
TTI | 达到可交互时间,推荐的响应时间是100ms以内否则有延迟 | Time To Interactive |
Long tasks | 超过了 50ms 的任务 | |
SSR&&CSR | 服务端渲染和客户端渲染 | Server-Side-Rendering / Client Side Rendering |
Isomorphic | 同构化 |
以一个h5页面打开为例
用chrome面板监控 FP、FCP、FMP、TTI
SPA性能问题
通常用 React/Vue 编写的代码打包后如下:
只有一个根节点,dom是由js解析之后生成虚拟dom -> dom diff -> 页面
解决方案: 可以采用SSR服务端渲染
把html内容填充进去,不过会牺牲TTFP时间。
小结
就像我们在电梯时会疯狂按关闭按键一样,用户是没有耐心等待一个页面的加载
,一个性能很差的页面很容易流失用户。
本文承接上面两篇文章,对整个流程做了一个总结,分析中间可以优化的步骤,当然,这里只是尽可能多的举出优化的方案,参考链接中会给出一些比较好的优化整理,性能优化任重道远,本文会持续更新
。
参考链接
彻底弄懂强缓存与协商缓存
雅虎军规35条
前端性能优化小结
web前端性能优化总结
前端性能优化的七大手段
nginx缓存配置及开启gzip压缩
手机淘宝性能优化【分享】
前端性能优化 —— 减少HTTP请求
xikun's blog
作者:掘金-性能优化 让你的页面更丝滑