Fork me on GitHub

tag-2021-11-10-tag
72.png

开篇

优化网站是一个系统性和持续性的过程。很多人认为优化网站的性能只需要合并图片啦,减小HTTP请求啦,部署CDN啦就行,实际上这都是见木不见林的做法。以上的做法经常会被面试者提起,在被问到自己在网页优化的经验和技巧时,大多数人都是例举出以上的这些方法。无可否认,上面这方法都可以在某种程度上提高网页的加载性能,然而仅仅知道几种方法,显然还远远不够。就好像我们学习一门新语言,如果只是知道的零散的一些单词,我们是无法完整地、自由地表达自己的思想的。我们需要的是方法论,用系统性的思维来解决系统性的问题。所以,本篇博文不会带你去细究哪一种方法会带给你优化性能,这些细节在文中提供的链接的博文中都有非常详尽的介绍,本篇博文的重点是告诉你如何自顶而下地解决这类问题。

知识储备

追本溯源

一般来说,我们认为网站性能大概分为两种:加载性能交互性能。加载时间的长短以及交互反馈的及时性,能给用户带来不同的体验。一个好的Web应用在加载时间上都是非常短的,良好的交互性不仅能给用户及时的反馈,并且反馈的方式也更符合人的直觉,这样的应用会为你带来好的评价和口碑,最终达到商业上的成功。有些网站仅仅在首页加载速度上优化了零点几秒,就能创造几百万的收入。例如星巴克的网站首页自从改成了PWA,就给他们带来不小的商业利润。

加载瓶颈

加载性能指的是指用户从输入URL或者进入你的网站一直到可以与网页持续进行交互的这段时间。这段时间决定了用户对网页的整体评价。通常,越快的网页加载性能,会提升用户的留存概率,而较长的白屏时间,会降低用户的留存率,毕竟大家都这么忙,很少人会对着白色的屏幕发呆十几秒钟。造成网页加载的性能有很多:网络速度,硬件性能,代码的执行效率,资源的大小等都会影响我们看到完整界面的时间。你需要清晰地知道浏览器是怎么样呈现一张网页的,然后在顺着这条线去发现问题。

交互瓶颈

交互性能指的是,用户在网页可以完全交互后,在交互的过程当中,界面的流畅程度。交互性能一般与渲染帧数以及界面对用户的反馈有关系。人的眼睛能看到60帧(FPS)的动画为非常流畅,因此,如果界面的持续变化维持在60FPS会给用户的感官系统提供很好的反馈。其次是对输入行为的时间响应,如果事件延迟执行100~300ms用户就会感觉到响应延迟,从而给带来流畅性不佳的体验。

浏览器

浏览器是Web应用的主要载体,自诞生以来它已经走过了30多个春秋了,从最初的只渲染简单的HTML标签,到现在的万花筒式的缤纷世界,浏览器的进化速度已经超过我们这个时代了。前端工程师的主要战场就是浏览器,因此对浏览器的足够认知有助于我们开发出更好的应用和产品。浏览器的技术底层细节非常复杂,如果要细细研究会花费不少的时间,然而对其渲染流程有一些基础的了解却是必不可少的。例如:浏览器是如何渲染出网页的,以及它是怎么执行脚本的,还有它在整个程序运行中的结构是如何的。我在这篇文章中大致的分析了在地址栏中输入URL到网页展示的全过程,你可以查看帮助你更好了解浏览器原理。自从08年chrome诞生以来,浏览器就不再是一个黑盒子,google对浏览器上的技术开源以及持续改进,使得我们现在用的浏览器已经完全可以媲美一个操作系统了。这篇文章中更加详细的介绍了浏览器的细节,了解他们有助于你开发自己的应用,从底层开始构建自己的知识体系。
另外利用好浏览器提供给我们的工具能够极大地提高我们找到性能瓶颈的速度。google提供了非常专业的浏览器开发工具dev tools,非常契合我们开发人员的开发习惯。通过Performance或者Lighthouse等面板,我们可以找到一些在Lab环境下的优化点。总之,浏览器不管作为终端或者开发端,都是前端工程师必须深入的一个知识领域。

HTTP

HTTP协议是互联网的基石,我们看到的所有的资源,都是通过tcp/ip协议从远程的另外一台机器上交换过来的。事实上,http在首页性能优化上占据了很大一部分。在日常开发中,我们往往遇到的网络或者服务问题会比其他浏览器相关的问题要多。在浏览器飞速发展的时代,基于tcp的http协议在几十年的进化过程中也不断的完善自身,例如http1.x,http2以及未来的http3都时时刻刻在改进着我们交换信息的方式。http的系统知识非常多,也非常广,你需要平时不断的积累,观察,到底你的网站在网络这块还有多少的改进空间。具体的问题例如:http的重传机制,http的快速恢复,滑动窗口等。另外,了解和部署以及观察http缓存在前端开发来说几乎可以说是一个硬技能。我在这篇文章中较为深入的探讨了http缓存。与浏览器不一样,http的差异体现在服务器的部署和网络传输上面,较浏览器更少的依赖于客户端设备性能,因此在针对http优化是需要考虑的角度与浏览器不同。
最后,虽然我们的信息在光纤中传播的速度非常快,但是对于日益增长的需求来上来说,还不够快。考虑到现实世界上两地的距离以及物理条件,我们可以确定,http在物理层面很多地方还存在优化的可能。部署CDN是一个一举多得的举措,当然还有其他种种的措施。了解http将对你进行网站优化提供一个全面的知识体系的指导。这篇专栏对http进行了非常详尽的讲解,我推荐你去把它看完。

性能指标

虽然性能体验有部分是主观上,但是对于普遍的体验来说,我们还是可以通过一些客观的标准来对其进行衡量和评估。Google团队在一直在标准的制定上扮演着重要的角色。为了帮助开发者评估自己的网页的性能,他们提出了一些列的指标,这些指标大多数都建立在用户的视觉的反馈上,从白屏到可完整地持续性的交互,包含了复杂的算法逻辑,为的就是尽可能的反映网站的性能,你可以通过他们提供的工具来检测自己的网页性能。另外我在这篇博客中比较全面搜罗了这些指标的介绍,以及我对他们优劣的一些看法。最后要确定的是,如果我们的性能已经到了被感官感受到“慢”的时候,我们网页的内在问题其实就已经非常严重了。通过这些指标,我们可以更加细微客观的知道自己应用的短处。

工具

古人云,工欲善其事必先利其器。开发工具,测试工具,调试工具以及监控工具在前端的领域都有是不可不用的。时至今日,我们早已经不是使用IE6用alert来调试开发的时代了,当年的设计软件Dreamweaver也被大部分程序员淘汰了。靠着丰富开发的社区生态,我们可以站在巨人的肩膀上,搭建自己的工具链条。我在下面列出几种在开发中常见的性能调试工具,来帮助定位网页的性能:

1.Dev tools

相信任何做前端的工程师都离不开这个工具,它是集成到谷歌浏览器中的工具面板(在其他的浏览器中也有相关的工具,例如firefox的firebug等。我们对它们的统称为dev tools),提供给开发者专业全面的信息。其中功能非常丰富,你甚至可以在里面发现一些彩蛋。我在这个系列中比较全面地介绍了chrome的开发者工具一些用法,你感兴趣的话可以去看看。

这篇文章写成时间较早,相对于Chrome浏览器如今两个礼拜一个版本的速度来说显然有些落伍了。

2.Lighthouse

Lighthouse是一种基于web的网页测试性能的系统,你只需要在输入框中输入测试网站的地址,它就会给出我们之前提到过的各种指标。当然,这些指标只是基于特定的环境(网络,机器,浏览器)下进行评估的,不具备普遍性。Lighthouse集成在chrome浏览器中,你可以很方便地使用它对网页进行整体的性能评估。

3.Fiddler & Charles & Wirmsharp

FiddlerCharles分别是一款在window上和ios上的抓包工具。他们的功能都是非常丰富,提供了抓包,替换,监控请求的诸多功能。相对于前两者来说,wirmsharp在更深层次的信息上展示更加详细。但对于我们日常开发来说,选择前两者就足够了。抓包工具无论在开发还是在测试的过程中都非常有用,它不仅可以快速地定位问题的根源,而且在线上调试上有很好的辅助作用。

4.WebpageTest

Lighthouse一样,webpagetest也是基于网页的性能测试系统,同样是输入测试网站地址,它会给出结果,只不过它侧重http的方面的,而且在网络细度上具备丰富的可调节性,例如,可以测试某个地方的网页加载速度,可以在地图上选择即可。对CDN的应用的效果测试十分重要。

5.PageSpeed Insights

PageSpeed Insight也是google的一些性能服务报告。你只需要提供一个原始的url链接,它会帮助你分析你的网页性能。PSI与之前的工具不一样的是,它是基于谷歌爬虫的历史数据的,并非时时的对当前这次访问做各项性能数据统计。这对我们的性能评估工作有非常大的作用。PSI的缺点就是并非所有的网页都被google爬虫爬取,因此,在针对特定的应用来说,它的作用就显得比较小了。

6.Chrome User Experience Report

CUER是一项google的性能检测计划,通过引入google提供的脚本,将我们的客户端数据上报google,从而统计你的网页的性能报告和评估。开发者可通过查询该数据集来了解使用不同硬件、软件和网络的实际 Chrome 用户的上网体验。分析很多网络原点可帮助网站开发者和网络社区了解它们的表现出色之处,发现需要改进的领域。

7.Eruda

Eruda是在移动端开启调试的利器。它通过模拟PC端的devtools,提供给我们移动端的一个类似的dev tools的调试界面。在调试网络和缓存方面尤其有用。缺点就是功能远远不如桌面版真实的dev tools强大。这是一个阉割版本的调试工具,功能非常有限。

资源准备

You can't optimise what you don't measure。我们很多时候凭自己的感觉来判断一个网页的性能,然而往往人的感觉并不可靠。而且我们在判断一个网页的性能是只是单独的在一个特定的条件下做判断,这种判断其实是孤立的,不可靠的。当性能已经能被人的感观捕获的话,事情往往就已经太迟了。
在一个网站上线后我们需要对它进行持续的,全面的,广泛的性能检测。而这样一种工作的前提条件就是搭建一套性能监控系统。我在这篇文章里面讲到过如何去搭建一个性能监控系统。搭建一个监控系统并不容易,需要的人力和物力资源不在少数。在大型一点的公司,都有资源和人力控制自己的团队搭建一套完善的系统,在中小公司,我建议还是使用第三方的别人的优秀开源作品。

所以你在开始动手干大事之前,请确保你的资源协调能力,安排人员和资源,预估好时间,以免因为客观的因素半途而废。尤其是打算自己动手搭建监控系统的时候,往往需要统筹全局的权力去安排协调各个部门的人力。所以,对你的资源进行评估后再开始做这件事,做到未雨绸缪。

锱铢必较

预算

在搭建一个网页应用之前制定预算并不是天方夜谭。在一开始对网站应用的体积进行合理的预测,能够知道你后续在开发新功能和接受新需求时变得谨慎。合理地制定预算方式是需要一定的经验,而最终的预算值也并非一定要十分精确,只需要给出合理的预期即可。一般最好能够有参照的标准:例如你的竞争对手的应用,或者行业内做的最好,体验最好的那家企业的应用。通常随着功能的完善和丰富,我们的代码数量也会越来越多,时时刻刻对照着我们最初安排的那张“预算表”去完成搭建过程。另外,提前制定预算也可以在面对产品不合理的诉求时当挡箭牌(到时候加载慢可不能怨我哦)。

资源

web应用的丰富发展使得我们需要从服务器上加载的东西越来越多,尤其是图片,视频和字体等媒体资源,我们在一开始的时候就需要对他们进行一些处理。例如,压缩图片和视频使得体积更小巧,还有选择不同格式的图片可以有效的减小体积。Google developer上的一系列文章详尽的讲明白了图片以及视频的优化处理方式,以及如何找到合适的策略构建自己的资源。

积沙成塔

性能优化不是一蹴而就的,需要长时间的,反复的去实践。有可能我们发一次版本也就是解决一个很小的优化点。但是这些点经过时间的积累,最终会反馈到整体的网页性能上。保守的策略是逐步的解决性能问题。不论是优化一段代码,还是减少一条http请求,只要长期地,充满干劲的去朝着一个方向做优化工作,性能肯定得到有效的改进。

整体思维

预见未来

如果你是从头开始做一个项目,那么在某种程度上来说你的未来是由你自己的决定的。但事实是很多项目,我们接手过来时倒腾了好几手的,这些项目不幸现在落在了你的头上,你的老板于是叫你优化项目,这时候你一定要小心翼翼,以免掉到了别人给你的坑。而如果是个全新开始的新项目,那么你就能放手一搏了吗?不不不,在面临一个新的项目的时候,你同样需要小心翼翼的,这种小心是在预见上,而不同于之前的是在放手去做上。在选择某个功能的时候你需要仔细它思考,尤其在底层一些设计上,更需要兼顾功能和性能。

前期架构

前期架构多网站来说十分钟重要。我认为在架构方面的工作直接或者间接影响了我们在后面一些列的开发和优化的细节打方向。架构其实是属于选方向的。古语有云:“条条道路通罗马”。我们的一个产品,在对外功能上是统一的,但是实现的方式确实有很多种。例如,架构师在前期就需要根据各项指标评估,决定这个产品用什么样的方式去完成选用什么语言,以及何种方式监控后续的需求迭代。例如:PWASPA的优化逻辑不一样,MPASPA的优化也不一样,REACTVUE或者ANGLAR在细节上以及优化上的逻辑思路也是不一样的;又比如,我们网页应用的定位决定了我们是使用高清的图片还是质量次一点的小格式图片、字体等。虽然我们都可以用他们去实现统一的目标,但是考虑到人员,知识储备,维护,扩展等方面,架构师在选择这些重要的因素时,就应该多方思考,权衡利弊。或者使用APP SHELL或者其他形式承载你的应用。

编写代码

前端程序员经常被人戏称为API调用工程师,有时候不知道是不是应该感到该无奈?我认为如今进入前端这一领域已经很低了,而且在可预见未来,门槛会越来越低。如果你用过那种可视化IDE功能强大的web应用,你就应该知道,以后学习前端技术去做一个网页应用几乎只需要几天甚至几小时的学习时间就可以了。如今框架的兴起也方便了开发人员的工作量,而很多交互性能,我们基本上都可以有框架底层来给你解决。我们能做到的只能是在代码的可维护性上做做文章。(或者是使用for替代forEach提升性能o(╥﹏╥)o)。虽然如此,但这并不是你不去深入研究的原因。我认为在编写代码的过程刻意地使用关注底层CPU的计算性能优化虽然不太可能,但是我们可以通过其他方式提升业务性能,例如:根据业务类型安排还http的请求时序,根据框架提供的异步能力加载JavaScript或者其他资源,在某些复杂的计算上刻意地使用worker或者自己的算法能力等。只要你愿意学习进步,任何地方做任何事情都能够让你大展拳脚。

后期监控

后期监控我已经在很多地方强调过了。好的监控能帮我们发现系统的漏洞,性能的缺陷,我认为大多数人在功能完成后就很少持续关注现实的代码运行状况了,只是在临时发现了bug或者老板打电话怒气冲冲的指责网页加载速度慢的时候,才会去线上看看自己的代码,这种是属于被动的监控。真正的监控不止防范于未然,而且还能预测未来,对照现在,让我们在对比中不停的磨练自己写出更好的代码。

改革与革命

历史的教训

改革,在古代被称之为变法。回顾历史的变法者,功成名就的寥寥无几,大多数是以失败告终。而革命又因为是成功人写就的历史,往往是在即成的历史上对革命者歌功颂德,但实际确实残酷血腥而成就微小甚至反而不如前代。例如辛亥革命虽然革了大清朝的命,但在面对新中国的现代化等一些列问题时,毫无建树和改变。只是换了一个国号而已。我本人也不喜欢激进的做法,我比较相信时间能够抚平一切旧制度的缺陷,激烈的革命带来的往往是流血战争,真正需要转变的是人的思维和观念,消灭一个人很简单,要给人灌输观念就需要常年累月的付出。工业革命其实也是从逐步改良的蒸汽机而发展起来的,第二次,第三次的工业革命也是在低限度的、低技术含量的第一次工业革命中的手工业改良而来的。
历史对改革者都不太公平。我们都知道商鞅也好,王安石也好,还有张居正和阚友伟,变法者的境遇都是十分悲惨。当然一部分原因是因为既得利益者势力过于强大,但是另外一部分是他们的错失太过于强硬和激进。历史告诉我们,一时的热情终究会消散,只有对目标有坚定的信仰并且懂得利用时间的人,才能达到自己的目的。伟大的事业不是一天只能完成的,这些道理同样适用于我们今天的主题。我认为在面对旧项目或者新项目的优化工作时,只要走对了方向,剩下的还是要交给时间。

环境与现实

如果你都是个性能优化老手,在精通了各项性能要素以及优化性能的方法后,你这时候需要面对一个现实的问题。这个问题也是在我在后续优化的时候遇到的:你的优化方案的现实性。我说的实现性是指公司环境,团队的技术能力,时间等客观条件。我曾经天真得以为如果自己什么都懂,就能什么都做。后来我才知道,很多事情并不是自己知道就能做的成功。例如你在搭建监控环境时需要的服务器资源,你在优化时具体到每个项目以及与这些项目负责人的沟通,还需要考虑当前你自己的工作量,排期,最后还需要考虑你这样做是否符合公司的基本要求,领导是否对你支持,公司环境(软硬件)限制等等,这时候你就需要给自己一些软技能,包括沟通能力,分享能力还有一点点小滑头。如果实在不行,那只能用脚投票了。

最终的抉择

性能在不明显的时候既主观也客观,通过数据和指标,我们可以客观地评估一个网页应用是否存在性能问题。主观是因为每个人对网页加载或者运行的感官是不一样的(你在非洲和欧洲上网时对网页加载速度的预期是不一样的)。我们即可以通过上面所学知识来达到优化目的,同时也可以通过一个简单的loading来反馈给用户,让他在主观意识上减少性能加载缓慢带来的心理焦虑。或者两者都同时采用。当然无论你猜用何种方式,最终我可以通过数据来了解在性能这块上,用户的感受。例如留存率,留存时间等。

总结

很可惜,这个世界上速成的东西大多数都很廉价。在需要对既有的项目进行优化时你要做的和掌握的知识就得非常系统,并且在细节上有清晰的认识。而且改进性能这件事情上需要持续的投入精力才能逐步看到结果。性能优化其实需要掌握的知识是很广的,有些知识需要深入理解,但总体上,这些知识学习的成本和难度不高。你需要多方面的积累经验,需要慢慢的摸索,掌握规律。没有捷径。

引用文档

Google Developers Document
Goolge Web Fundamentals

posted on 2021-11-15 08:41  chen·yan  阅读(871)  评论(0编辑  收藏  举报