0x00 大纲
- 0x00 大纲
- 0x01 前言
- 0x02 书接上回
-
0x03 性能调优
- DNS 预获取(DNS-prefetch)
- 预连接(preconnect)
- 预加载(preload)
- 减少不必要的 HTTP 调用
- 使用自定义的语法高亮
- 进一步精简 JavaScript 和 CSS
- 性能辅助分析
- 0x04 小结
0x01 前言
四个月前,我在《你是来找茬的吧?对自己的博客进行调优》一文中探讨了以博客的使用者而不是开发者身份去进行优化,究竟能做到何种程度的问题。当时以 Edge 浏览器的开发者工具里的 lighthouse 评分和加载时间作为基准,经过一系列的针对性优化调整,将博客首页的评分逼近到了“性能(99/100)”、“无障碍阅读(100/100)”的水平,但是当时有一个遗憾,就是没能完成双百,那么时隔多日,这次就要集中一点,登峰造极,完成双百挑战。
0x02 书接上回
lighthouse 评分如下:
既然堵不住,那能不能加速呢?
0x03 性能调优
DNS 预获取(DNS-prefetch)
https://common.cnblogs.com/
https://images.cnblogs.com/
https://pic.cnblogs.com/
https://blog-static.cnblogs.com/
https://account.cnblogs.com/
我们打开命令提示符或者其它你喜欢的终端,输入nslookup
命令(注意不能用ping
指令,部分服务器出于安全考虑,是禁用 ICMP 协议访问的),查看各个域名对应的 DNS 解析地址,就会发现它们的 IP 地址是不一样的,以主站和 pic.cnblogs.com 为例:
DNS-prefetch
(DNS 预获取 是尝试在请求资源之前解析域名。这可能是后面要加载的文件,也可能是用户尝试打开的链接目标。DNS-prefetch
可帮助开发人员掩盖 DNS 解析延迟。
<link rel="dns-prefetch" href="//common.cnblogs.com">
<link rel="dns-prefetch" href="//images.cnblogs.com">
<link rel="dns-prefetch" href="//pic.cnblogs.com">
<link rel="dns-prefetch" href="//blog-static.cnblogs.com">
<link rel="dns-prefetch" href="//account.cnblogs.com">
注意这里不需要添加主站的地址,因为主站的 DNS 在浏览器访问那一刻已经被解析过了。
预连接(preconnect)
DNS-prefetch
仅执行 DNS 查找,但preconnect
会建立与服务器的连接。如果站点是通过 HTTPS (提供)服务的,则此过程包括 DNS 解析,建立 TCP 连接以及执行 TLS 握手。将两者结合起来可提供进一步减少跨域请求的感知延迟的机会。
<link rel="preconnect" href="//common.cnblogs.com">
<link rel="preconnect" href="//images.cnblogs.com/">
<link rel="preconnect" href="//pic.cnblogs.com/">
<link rel="preconnect" href="//blog-static.cnblogs.com/">
<link rel="preconnect" href="//account.cnblogs.com/">
我们看下效果,以userinfo
接口调用为例(访问 account.cnblogs.com)为例,增加 DNS 预获取优化之前耗时是这样的:
预加载(preload)
以自定义的头像为例,需要由自定义的主题脚本通过prepend
的方式动态添加节点,这意味着主题脚本和jquery-2.2.0.min.js
完成加载之前,该头像都暂时不可用。但是头像的 URL 地址我们是预先知道的,这个等待就白白浪费了许多时间。
<link rel="preload" as="image" href="//images.cnblogs.com/likecs_com/mylibs/1647185/o_200214034545avatar.png">
减少不必要的 HTTP 调用
loadBlogDefaultCalendar函数发起的,这个函数定义在blog-common.min.js
文件里——上一篇文章提到过,这个文件是默认加载的,是博客园的公共JavaScript函数库,无法屏蔽。
loadBlogDefaultCalendar是作为全局函数发起匿名调用的,那么在blog-common.min.js
文件加载之后,loadBlogDefaultCalendar
函数执行之前,我们是可以利用JavaScript Function Hijacking把它替换掉的,像这样:
<script>window.loadBlogDefaultCalendar=Function.prototype</script>
它刚好可以与前面所有的优化一起放在博客园后台-设置页面中“页首 HTML 代码”处,保存后刷新页面,再看原来的 AJAX 请求已经没有了:
使用自定义的语法高亮
prism.js语法高亮,它会根据页面中的language type
自动加载对应语言的高亮模块。对于一个页面有多种语言或开启了行号显示的情况,可能会发生多次的模块加载,那么你会在控制台看到prism-autoloader.min.js
同时加载了若干个prism-*
开头的脚本。那为什么说是可能呢?因为prism.js
里面其实已经集成了多种常用语言,除非你用到了里面没有的语言模块或者插件,才会触发加载动作。
prism.js的官网上可以很方便的定制模块,只勾选自己常用的几种语言即可,BTW,我还使用了彩虹括号插件……总之,像买菜一样选择自己想要的东西就好了:
进一步精简 JavaScript 和 CSS
在开发者工具里找到”覆盖范围“标签,如果没有,可能要点击旁边的”+“号手工添加。点击”开始检测覆盖率并刷新页面“,覆盖率统计在你手工点击停止前会一直进行,这时候你可以去页面进行各种操作,尽可能地触发代码。随后在覆盖率报告中,可以看到当前各个 JavaScript 和 CSS 的使用情况:
这样做的目的是找出优先加载和优先执行项,如果脚本和样式表体积较大,就可以按照执行优先级拆分,利用前面提到的预加载(preload)技术将最基础部分优先加载,后续使用到的脚本和样式延迟加载或者按需加载。尽量减少或加快关键资源的加载,依然是提高 FP、FCP 和 LCP 分数的关键。
性能辅助分析
lighthouse 能帮你评估页面的总体情况的话,那么性能分析工具则可以助你从细节入手找到瓶颈。同为开发者工具里,切换到“性能”标签,点击”开始分析并重新加载页面“按钮,能够自动刷新当前页面并对其进行采样分析,最终生成的报告如下所示:
如果性能报告中出现了红色三角形长任务(被标记红色),也是需要重点关注的,它指示主线程上耗时过长且性能缓慢的工作,通过查看对应时间轴火焰图上最宽的部分,找到耗时的原因。
另一类比较关键的事件是”重新计算样式“事件,如果发现了长时间运行的 “重新计算样式”事件,可以选中它,然后在下方点击 “选择器统计信息”功能来了解哪些 CSS 选择器占用的时间最多。从我的个人经验来看,通常来说 CSS 的优化收益不是很大(微秒级),除非有很严重的性能问题,选择前面几项耗时最突出的选择器进行优化是比较划算的方案。
0x04 小结
在经过一系列的究极折磨后,这是首页最终的 lighthouse 评分:
(0.1×98 + 0.1×100 + 0.25×99 + 0.3×100 + 0.25×100/(0.1 + 0.1 + 0.25 + 0.3 + 0.25 = 99.55
看来还可以继续寻找新的优化方法。