接下来我会逐个请求分析youtube究竟使用那些国内大家不那么常用的技术,因为点会比较多我在正文中就不一一详细介绍了但都会配上相关阅读连接,我只会对与带来关键性能提升的部分做展开分析。
从截图可见youtube在html文档和静态资源请求上都启用了http/2 + quic/46,http/2相信还有比较多人已经开始尝试使用了,但quic在生产环境使用的并不多见。QUIC(Quick UDP Internet Connection)是google自spdy后推出的新的协议,从名字就能看到它最大的区别是使用UDP传输协议,这可以说是对http/2是一个关键的补充,因为在现实世界中我们会遇到http/2队头阻塞问题,在丢包比较严重的环境下http/2的性能是会有所下降的,而在网页这种多请求并发的情况下由于http/2的多路复用(同一个域名下共享一个tcp)的情况下http/2的整体性能甚至会比http1.1更差,而quic在解决了tcp的队头阻塞的同时实现了0RTT数据传输,连接迁移等新特性。
用最直观的感受来解释就是使用quic后网站的性能提升15%,弱网环境提升20%,如果你的用户会频繁的wifi 4g之间切换或者经常乘坐高铁、地铁高速移动,quic让他们ip变更时不要重新建联,这对视频网站来说是非常有意义的提升。
cnblogs.com/jb2011/p/84
52im.net/thread-1309-1-
首页的设置是浏览器默认设置我们就不需要讨论了,但播放页的设置不同origin-when-cross-origin的目标是保护隐私,因为播放页是带参数的,为了避免被下一跳的第三方页面知道用户是从哪个视频内容发生的跳转所以只返回host信息
developer.mozilla.org/z
alt-svc的全名是HTTP Alternative Services,服务端可以将自己的替代服务地址以协议规定的方式告诉浏览器,对于支持这个协议的浏览器来说,后续请求都会使用新地址。除了提供替代服务外,理论上我们还能通过这个字段的设置来引导用户访问不同的多语言版本或者abtest版本哦。
imququ.com/post/http-al
与常见的通用压缩算法不同,br(Brotli)使用一个预定义的120千字节字典。该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库。
zh.wikipedia.org/wiki/B
tools.ietf.org/html/rfc (你是不是很好奇这120千字节的字典里有什么?)
通常简称为HSTS是一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP。
developer.mozilla.org/z
安全响应头
imququ.com/post/web-sec
允许哪个域名可以访问当前资源的Resource Timing API提供的相关信息。
developer.mozilla.org/z
我们可以看到第五个请求是一个html文档,它是通过一个比较有趣的方式引入到页面当中的:import html
https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/HTML导入 已不建议使用
css请求header中完成预连接算是相对少见的做法,但在css内部引用了较多非当前域名资源的情况下在http header里声明预连接会比在当前页面或前置页面用通过<link perconnect>要更通用一些,因为你不需要考虑前置页面都有哪些。
w3.org/TR/resource-hint
cdnplanet.com/blog/fast
允许访问Content-Length,应该是为了做客户端资源加载速度的分析而提供的信息。
developer.mozilla.org/z
inline声明图片应该被行内显示而不是作为附件下载,filename是下载时使用的默认名称
rfc-editor.org/rfc/rfc1
AJAX http header
https://zh.wikipedia.org/zh-hans/隱私權偏好平台
允许同步和定时更改网页的呈现, 即DOM元素的动画。它通过组合两个模型来实现:时序模型 和 动画模型。
developer.mozilla.org/z (api介绍)
github.com/web-animatio (实现)
github.com/web-animatio (polyfill)
允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。
developer.mozilla.org/z
github.com/webcomponent
polymer-zh.cn/
requestIdleCallback & cancelIdleCallback
会在浏览器空闲时期依次调用函数, 这就可以让开发者在主事件循环中执行后台或低优先级的任务,而且不会对像动画和用户交互这样延迟敏感的事件产生影响。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。
developer.mozilla.org/z
developer.mozilla.org/z
一个轻量级的JS框架,用于把youtube改造为一个单页应用。
SPF
normal
youtube.github.io/spfjs
github.com/youtube/spfj
youtube.com/watch?
在一次页面跳转的过程:<a href = "feed/trending"> 为普通连接,点击后被network.js劫持后发出为feed/trending?pbj=1的请求
在返回头中有如此信息:x-spf-response-type:multipart
返回的正文从html变成了一个json对象,包含了渲染对应模块所需的数据。
同类实现算是比较多的,facebook早年的bigpipe,微博都有使用类似的技术减少连续访问时相同模块的重复渲染浪费。
Part3 性能分析
上面科普了挺多的技术点,或多或少都跟性能有些关系。这部分请跟随我的视角来看看性能方面youtube还做了哪些优化。
内联脚本与CSS
查看页面源代码我们可以看到youtube的html是做了SSR的,但并没有做data→dom的这一步,因此当中不仅有模块初始化的JS、CSS代码外,还有包含关键数据的JSON。观察下来youtube页面基本遵循了一个规律,有共性需要的js、css才做外联,当前页面所必须的js与css做内联。可能一部分同学会质疑这个做法与曾经的优化建议里说的不一样,经过B站自己的实验证明,在html文件体积可控的情况下把页面必须的js、css内联,首屏的渲染速度会有较大的提升,其收益主要来自减少了http建联的时间。在用户真实的使用场景当中,每有一个请求在播放器初始化之前,哪怕是一个http204的请求都会对我们视频首帧播放的8分位时间有50-100ms的影响。
另外,我们还发现一点是youtube对播放的依赖进行了较好的治理,大家可以尝试把红框内的所有请求都block掉,再刷新页面
你会神奇的发现,虽然样式有一些错乱,播放器意外的模块加载失败,但播放器与视频依然保持正常运作。虽然这不是正常用户的行为,但能做到这一点并关联上文中提到的requestIdleCallback & cancelIdleCallback的空闲时执行的调度能力,我们知道虽然这些脚本的加载在播放器之前,但是他们的执行时机完全可以被后置,最终实现播放器的优先渲染。
从连续截图中我们也可以印证这一点
如果我们对xhr等数据请求做同样的处理,我们还能印证另外一点,就是首屏渲染的所有数据都已经在SSR中提供了,不需要额外的请求接口。
从页面源代码我们还能看到另外一点是youtube的icon全都是用svg实现的,这是和他们采取的扁平化的设计是分不开的,而内联的svg不仅仅带来了体积小、连接数少的好处,如果你仔细观察你还会看到大部分的icon都是有小动效的,这些动效是依靠svg动画实现的,比传统的gif或者序列帧动画体积可要小太多了。
youtube的设计几经修改后最后固化为当前我们熟悉的版本,在不同的页面跳转过程中顶部和侧边栏菜单是作为常驻模块存在,只需要渲染右侧的content。对于大多前端来说新做一个spa项目是相对容易的,而对于youtube这个庞大的网站而言通过重构把多页面重构为单页面的代价远大于收益,因此他们是通过spf.js框架来解决这个问题的,劫持全局A链接的点击事件,只请求下一个页面渲染所需的数据在当前页面完成渲染,避免了大量无意义的http建联和模块重新渲染的开销,加快了页面渲染的速度。
而在视频连续播放的场景中,播放器的初始化也是一个巨大的开销往往要需要400-600ms来完成,在spf.js的加持下播放器不需要重新初始化只需要载入下一个视频的数据即可。如果你觉得体验youtube比较困难的话,你可以来b站试试,访问右侧的相关推荐我们同样重用了页面和播放器,此时从点击卡片到视频能够播放只需要500ms不到的时间。
跨页面缓存
无缓存访问
有缓存访问
通过上图可以看到youtube的静态资源是有冗余部分的而且体积相当的大(300k的js 600k的import html),并没有按页面维度进行最小化的打包,这应该是为了做成spa后下一个页面的渲染不需要请求更多的资源即可完成,从单个页面加载速度来看这显然是不划算的,不知道youtube是不是经过自己的实验证明了在用户连续访问的场景中这样做的整体收益更大呢?
视频网站的关键速度是首帧时间,影响这个时间的除了我们前面分析的页面加载顺序和资源优化外,很重要一点就是视频格式,而这当中youtube的魔法是真的多。在youtube的分享中我们可以看到目前youtube主要使用的是vp9,它只需要h.264一半的体积就能提供相同的画质
youtube.com/watch?
另一项魔法如上图,我们可以看到一帧画面被分割成了不同尺寸的格子,youtube对此进行了自动量化的实验,目的是对于视觉敏感的区域输出更多的细节,对于不敏感的区域降低细节。
vp9的窄带高清的能力,在全球范围内为youtube带来了非常可观的增长。在你可能因为vp9感到兴奋时,youtube去年在vp9的基础上又再推出了av1,av1比vp9体积又减少了30%。
未来在移动设备上还有会有原生支持。
末尾
我们来回顾一下从分析youtube代码我们得到了哪些优化建议:
最后补充一点:Node ssr是好东西,有了它前面几点才能在团队的闭环里完成不需要求人。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有