嗨,送你一张Web性能优化地图

  • 时间:2018-07-21 23:34 作者:前端小学生 来源:前端小学生 阅读:183
  • 扫一扫,手机访问
摘要:我们都知道对于Web应使用来说性能很重要。然而性能优化相关的知识却非常的庞大并且杂乱。对于性能优化需要做些什么以及性能瓶颈是什么,通常我们并不清楚。不包括那些对性能优化有丰富经验的高手事实上关于Web性能有很多可以优化的点,其中涉及到的知识大致可以划分为几类:度量标准、编码优化、静态资源优化、交付优

我们都知道对于Web应使用来说性能很重要。然而性能优化相关的知识却非常的庞大并且杂乱。对于性能优化需要做些什么以及性能瓶颈是什么,通常我们并不清楚。

不包括那些对性能优化有丰富经验的高手

事实上关于Web性能有很多可以优化的点,其中涉及到的知识大致可以划分为几类:度量标准、编码优化、静态资源优化、交付优化、构建优化、性能监控。

嗨,送你一张Web性能优化地图

图1. 性能优化分类

本文主要详情性能优化需要做的事以及需要考虑的问题。目的在于给读者脑海中生成一个宏观的地图。

不会详情每个优化项目具体如何操作。PS:后续会有系列文章针对不同优化分类下的具体优化操作进行更详细的详情。

1. 度量标准与设定目标

在进行性能优化之前,我们需要为应使用选择一个正确的度量标准(性能指标)以及设定一个正当的优化目标。

并不是所有指标都同样重要,这取决于你的应使用。最后根据度量标准设定一个现实的目标。

1.1 度量标准

下面是少量值得考虑的指标:

  • 初次有效绘制(First Meaningful Paint,简称FMP,当主要内容呈现在页面上)英雄渲染时间(Hero Rendering Times,度量使用户体验的新指标,当使用户最关心的内容渲染完成)可交互时间(Time to Interactive,简称TTI,指页面布局已经稳固,关键的页面字体是可见的,并且主进程可使用于解决使用户输入,基本上使用户可以点击UI并与其交互)输入响应(Input responsiveness,界面响应使用户输入所需的时间)感知速度指数(Perceptual Speed Index,简称PSI,测量页面在加载过程中视觉上的变化速度,分数越低越好)自己设置指标,由业务需求和使用户体验来决定。

FMP与英雄渲染时间非常类似,但它们不一样的地方在于FMP不区分内容能否有使用,不区分渲染出的内容能否是使用户关心的。

1.2 设定目标

  • 100毫秒的界面响应时间与60FPS速度指标(Speed Index)小于1250ms3G网络环境下可交互时间小于5s重要文件的大小预算小于170kb

以上四种指标的设定都有据可循。详细信息请查看RAIL性能模型。

2. 编码优化

编码优化涉及到应使用的运行时性能,本小节详情几个可以提升程序运行时性能的建议。

2.1 数据读取速度

事实上数据访问速度有快慢之分,下面列出几个影响数据访问速度的因素:

  • 字面量与局部变量的访问速度最快,数组元素和对象成员相对较慢变量从局部作使用域到全局作使用域的搜索过程越长速度越慢对象嵌套的越深,读取速度就越慢对象在原型链中存在的位置越深,找到它的速度就越慢

推荐的做法是缓存对象成员值。将对象成员值缓存到局部变量中会加快访问速度

2.2 DOM

应使用在运行时,性能的瓶颈主要在于DOM操作的代价非常昂贵,下面列出少量关于DOM操作相关提升性能的建议:

  • 在JS中对DOM进行访问的代价非常高。请尽可能减少访问DOM的次数(建议缓存DOM属性和元素、把DOM集合的长度缓存到变量中并在迭代中用。读变量比读DOM的速度要快很多。)重排与重绘的代价非常昂贵。假如操作需要进行屡次重排与重绘,建议先让元素脱离文档流,解决完毕后再让元素回归文档流,这样浏览器只会进行两次重排与重绘(脱离时和回归时)。善于用事件委托

2.3 流程控制

下面列出少量流程控制相关的少量可以稍微提升性能的细节,这些细节在大型开源项目中大量运使用(例如Vue):

  • 避免用for...in(它能枚举到原型,所以很慢)在JS中倒序循环会稍微提升性能减少迭代的次数基于循环的迭代比基于函数的迭代快8倍使用Map表代替大量的if-else和switch会提升性能

3. 静态资源优化

Web应使用的运行离不开静态资源,所以对静态资源的优化至关重要。

3.1 用Brotli或者Zopfli进行纯文本压缩

在最高级别的压缩下Brotli会非常慢(但较慢的压缩最终会得到更高的压缩率)以至于服务器在等待动态资源压缩的时间会抵消掉高压缩率带来的好处,但它非常适合静态文件压缩,由于它的解压速度很快。

用Zopfli压缩可以比Zlib的最大压缩提升3%至8%。

3.2 图片优化

尽可能通过srcset,sizes和元素用响应式图片。还可以通过元素用WebP格式的图像。

响应式图片可能大家未必听说过,但响应式布局大家一定都听说过。响应式图片与响应式布局相似,它可以在不同屏幕尺寸与分辨率的设施上都能良好工作(比方自动切换图片大小、自动裁切图片等)。

当然,假如您不满足这种尺度的优化,还可以对图片进行更深层次的优化。例如:模糊图片中不重要的部分以减小文件大小、用自动播放与循环的HTML5视频替换GIF图,由于视频比GIF文件还小(好消息是未来可以通过img标签加载视频)。

4. 交付优化

交付优化指的是对页面加载资源以及使用户与网页之间的交付过程进行优化。

4.1 异步无阻塞加载JS

JS的加载与执行会阻塞页面渲染,可以将Script标签放到页面的最底部。但是更好的做法是异步无阻塞加载JS。有多种无阻塞加载JS的方法:defer、async、动态创立script标签、用XHR异步请求JS代码并注入到页面。

但更推荐的做法是用defer或者async。假如用defer或者async请将Script标签放到head标签中,以便让浏览器更早地发现资源并在后端线程中解析并开始加载JS。

4.2 用Intersection Observer实现懒加载

懒加载是一个比较常使用的性能优化手段,下面列出了少量常使用的做法:

  • 可以通过Intersection Observer推迟加载图片、视频、广告脚本、或者任何其余资源。可以先加载低质量或者模糊的图片,当图片加载完毕后再用完整版图片替换它。

推迟加载所有体积较大的组件、字体、JS、视频或者Iframe是一个好主意

4.3 优先加载关键的CSS

CSS资源的加载对浏览器渲染的影响很大,默认情况下浏览器只有在完成标签中CSS的加载与解析之后才会渲染页面。假如CSS文件过大,使用户就需要等待很长的时间才能看到渲染结果。针对这种情况可以将首屏渲染必需使用到的CSS提取出来内嵌到中,而后再将剩余部分的CSS使用异步的方式加载。可以通过Critical做到这一点。

4.4 资源提醒(Resource Hints)

Resource Hints(资源提醒)定义了HTML中的Link元素与dns-prefetch、preconnect、prefetch与prerender之间的关系。它可以帮助浏览器决定应该连接到哪些源,以及应该获取与预解决哪些资源来提升页面性能。

4.4.1 dns-prefetch

dns-prefetch可以指定一个使用于获取资源所需的源(origin),并提醒浏览器应该尽可能早的解析。

4.4.2 preconnect

preconnect使用于启动预链接,其中包含DNS查找,TCP握手,以及可选的TLS协议,允许浏览器减少潜在的建立连接的开销。

4.4.3 prefetch

Prefetch使用于标识下一个导航可能需要的资源。浏览器会获取该资源,一旦将来请求该资源,浏览器可以提供更快的响应。

浏览器不会预解决、不会自动执行、不会将其应使用于当前上下文。

as与crossorigin选项都是可选的。

4.4.4 prerender

prerender使用于标识下一个导航可能需要的资源。浏览器会获取并执行,一旦将来请求该资源,浏览器可以提供更快的响应。

浏览器将预加载目标页面相关的资源并执行来预解决HTML响应。

4.5 Preload

通过一个现有元素(例如:img,script,link)公告资源会将获取与执行耦合在一起。然而应使用可能只是想要先获取资源,当满足某些条件时再执行资源。

Preload提供了预获取资源的能力,可以将获取资源的行为从资源执行中分离出来。因而,Preload可以构建自己设置的资源加载与执行。

例如,应使用可以用Preload进行CSS资源的预加载、并且同时具有:高优先级、不阻塞渲染等特性。而后应使用程序在合适的时间用CSS资源:

Link: ; rel=preload; as=style

4.6 快速响应的使用户界面

PSI(Perceptual Speed Index,感知速度指数)是提升使用户体验的重要指标,让使用户感觉到页面的反馈比没有反馈体验要好很多。

可以尝试用骨架屏或者增加少量Loading过渡动画提醒使用户体验。

输入响应(Input responsiveness)指标同样重要,甚至更重要。试想,使用户点击了网页后缺毫无反应会是什么心情。JS的单线程大家已经不能再熟习,这意味着当JS在运行时使用户界面处于“锁定”状态,所以JS同步执行的时间越长,使用户等待响应的时间也就越长。

据调查,JS执行100毫秒以上使用户就会显著觉得网页变卡了。所以要严格限制每个JS任务执行时间不能超过100毫秒。

处理方案是可以将一个大任务拆分成多个小任务分布在不同的Macrotask中执行(浅显的说是将大的JS任务拆分成多个小任务异步执行)。或者者用WebWorkers,它可以在UI线程外执行JS代码运算,不会阻塞UI线程,所以不会影响使用户体验。

应使用越复杂,主动管理UI线程就越重要

5. 构建优化

现代前台应使用都需要有构建的过程,项目在构建过程中能否进行了正当的优化,会对Web应使用的性能有着巨大的影响。例如:影响构建后文件的体积、代码执行效率、文件加载时间、初次有效绘制指标等。

5.1 用预编译

拿Vue举例,假如您用单文件组件开发项目,组件会在编译阶段将模板编译为渲染函数。最终代码被执行时可以直接执行渲染函数进行渲染。而假如您没有用单文件组件预编译代码,而是在网页中引入vue.min.js,那么应使用在运行时需要先将模板编译成渲染函数,而后再执行渲染函数进行渲染。相比预编译,多了模板编译的步骤,所以会白费很多性能。

5.2 用 Tree-shaking、Scope hoisting、Code-splitting

Tree-shaking是一种在构建过程中清理无使用代码的技术。用Tree-shaking可以减少构建后文件的体积。

目前Webpack与Rollup都支持Scope Hoisting。它们可以检查import链,并尽可能的将散乱的板块放到一个函数中,前提是不能造成代码冗余。所以只有被引使用了一次的板块才会被合并。用Scope Hoisting可以让代码体积更小并且可以降低代码在运行时的内存开销,同时它的运行速度更快。前面2.1节详情了变量从局部作使用域到全局作使用域的搜索过程越长执行速度越慢,Scope Hoisting可以减少搜索时间。

code-splitting是Webpack中最引人注目的特性之一。此特性能够把代码分离到不同的bundle中,而后可以按需加载或者并行加载这些文件。code-splitting可以使用于获取更小的bundle,以及控制资源加载优先级,假如用正当,会极大影响加载时间。

5.3 服务端渲染(SSR)

单页应使用需要等JS加载完毕后在前台渲染页面,也就是说在JS加载完毕并开始执行渲染操作前的这段时间里浏览器会产生白屏。

服务端渲染(Server Side Render,简称SSR)的意义在于弥补主要内容在前台渲染的成本,减少白屏时间,提升初次有效绘制的速度。可以用服务端渲染来取得更快的初次有效绘制。

比较推荐的做法是:用服务端渲染静态HTML来取得更快的初次有效绘制,一旦JavaScript加载完毕再将页面接管下来。

5.4 用import函数动态导入板块

用import函数可以在运行时动态地加载ES2015板块,从而实现按需加载的需求。

这种优化在单页应使用中变得尤为重要,在切换路由的时候动态导入当前路由所需的板块,会避免加载冗余的板块(试想假如在初次加载页面时一次性把整个站点所需要的所有板块都同时加载下来会加载多少非必需的JS,应该尽可能的让加载的JS更小,只在首屏加载需要的JS)。

用静态import导入初始依赖板块。其余情况下用动态import按需加载依赖

5.5 用HTTP缓存头

正确设置expires,cache-control和其余HTTP缓存头。

推荐用Cache-control: immutable避免重新验证。

6. 其余

其余少量值得考虑的优化点:

  • HTTP2用最高级的CDN(付费的比免费的强的多)优化字体其余垂直领域的性能优化

7. 性能监控

最后,你可能需要一个性能检测工具来持续监视网站的性能。

8. 总结

最后使用一张图来总结这篇文章所表达的内容,感谢@anjia帮忙画的这张图。

嗨,送你一张Web性能优化地图

  • 全部评论(0)
最新发布的资讯信息
【系统环境|Linux】零基础如何学好大数据?必备需要学习知识(2019-06-18 11:54)
【系统环境|】Hadoop环境中管理大数据存储八大技巧(2019-06-15 11:01)
【系统环境|服务器应用】现在国内IT行业是不是程序员过多了?(2019-06-11 06:34)
【系统环境|服务器应用】新贵 Flutter(2) 自己设置 Widget(2019-06-11 06:34)
【系统环境|服务器应用】Android完整知识体系路线(菜鸟-资深-大牛必进之路)(2019-06-11 06:34)
【系统环境|服务器应用】Java程序员小伙经历三个月备战,终获阿里offer(2019-06-11 06:34)
【系统环境|服务器应用】每日一问:谈谈对 MeasureSpec 的了解(2019-06-11 06:34)
【系统环境|服务器应用】【科普】晶体管-1(2019-06-11 06:34)
【系统环境|服务器应用】一个很多人都会答错的java基础题(2019-06-11 06:33)
【系统环境|服务器应用】深入了解枚举类型(2019-06-11 06:33)
手机二维码手机访问领取大礼包
返回顶部