对于前端性能优化你理解多少?很多人都晓得雅虎军规,然而你晓得为什么吗?

Vitaly Friedman写了一篇对于前端性能优化的清单,外面援用了至多六七百篇参考链接,具体介绍了前端性能优化相干常识,强烈建议大家好好浏览一下,包含援用的文章。英语浏览有艰难的,去年京东的WecTeam团队也针对此篇文件进行了翻译,当然,那是去年的版本了。

Front-End Performance Checklist 2021[1]
https://www.smashingmagazine....

我学到了很多,心愿你也一样,如有任何谬误欢送指出。

一、规范指标

性能优化,优化到什么水平,规范是什么?

(一)规范

● 至多比你最快的竞争对手快20%● 最大内容绘制(LCP)管制在2.5s内● 首屏展示平均值(SI)管制在3s内● 首次输出延时(FID)管制在100ms内● 累计阻塞时长(TBT)管制在300ms内● 累积布局变动量(CLS)管制在0.1内

(二)概念

1、比你最快的竞争对手快至多20%[2]

钻研表明,只有当你的页面比你的竞争对手快至多20%时,用户能力真正感知到你的页面真的比竞争对手的页面快。

与竞争对手相比,如果你的页面加载时长是5s,而竞争对手的是2s,就算你晋升了20%也是不行的,这个时候就须要与竞争对手作比拟。如果咱们做不到优化到2s,那咱们至多要优化到2s + 2 * 20% = 2.4s,这样至多用户不会感知到差别。

如果2.4s也做不到,这里还有一个心理阀值。以刚刚的2s、5s为例,大于此阈值的持续时间将被用户感知为靠近5秒。持续时间小于该阈值的持续时间将被视为靠近2秒。通过这种概念,咱们能够找到它的一个几何平均值:√(A × B),例子中就是:√(2 × 5) ≈ 3.2 seconds,如果加载工夫小于3.2s,用户能留神到差别,然而这对他们来说此差别对他们如何抉择服务并不重要。

2、最大内容绘制Largest Contentful Paint (LCP) [3]

LCP是一个页面加载时长的技术指标,用于示意以后页面中最重要/占比最大的内容显示进去的工夫点。LCP低于2.5s则示意页面加载速度低劣。

为了计算最大的元素,LCP会思考以下元素:

● <img>, <image> or <video> elements● Elements with background images. E.g: background-image: url()● Block level elements containing text

计算形式

可应用Largest Contentful Paint API

new PerformanceObserver((entryList) => {  for (const entry of entryList.getEntries()) {    console.log('LCP candidate:', entry.startTime, entry);  }}).observe({type: 'largest-contentful-paint', buffered: true});

还可应用第三方库web-vitals

import { getLCP } from 'web-vitals';// 能够发送到监控零碎getLCP(console.log);

为了掂量用户感知页面加载进度的要害工夫,咱们还有一些其余的指标,但都多多少少有些缺点:

指标定义毛病
首次内容渲染(FCP)First Contentful Paint浏览器出现第一块DOM内容的工夫通常与用户无关(如:loading、导航栏)
首次无效渲染(FMP)First Meaningful Paint在页面加载期间,计算的最大的布局更改后的绘制工夫1、没有标准化,很难跨浏览器实现;2、大概20%的状况不精确与SI相比,它更容易了解,与SI的后果类似,且在RUM工具中更易于计算和报告。

影响因素:迟缓的服务器响应工夫,阻塞的CSS、JavaScript,网页字体加载,低廉的渲染或绘画操作,提早加载的图像,骨架屏幕或客户端渲染

优化形式:

● 打消阻塞渲染资源● 通过加载具备正确优先级和正确程序的资源来最小化要害申请链● 压缩图像,并为不同的设施提供不同的图像大小● 通过最小化文件和提取要害的CSS来优化CSS● 应用字体加载策略来防止不可见文本(FOIT)的闪现

LCP评分低的次要起因通常是图像。要在Fast 3G上以小于2.5s的速度交付LCP——托管在一个优化良好的服务器上,所有动态的没有客户端渲染,并且有一个来自专用图像CDN的图像——意味着最大的实践图像大小只有大概144KB。这就是为什么响应式图像很重要,以及提前预加载要害图像(应用预加载)的起因。

在DevTools中,你能够将鼠标悬停在Performance面板“Timing”下的LCP栏上,以发现什么元素触发了LCP。

3、首屏展示平均值Speed Index(SI)

Speed Index是掂量页面性能的指标,显示页面的可见局部的均匀工夫。该值越低越好,SI低于3s则示意页面加载速度良好。

计算形式:须要可能计算在页面加载期间,各个工夫点“实现”了多少局部。在WebPagetest中,通过捕捉在浏览器中加载页面的视频并查看每个视频帧(在启用视频捕捉的测试中,每秒10帧)来实现的。计算比较复杂,有趣味的同学能够翻阅材料。

它是一个简单的指标,不容易解释;且计算密集,所以它不能用于任何支流浏览器的实在用户监控(RUM)。

优化形式:

● 优化内容效率:打消不必要的下载,应用压缩技术优化每个资源的传输编码,尽可能利用缓存打消冗余下载● 优化要害渲染门路:只加载以后页面渲染所需的必要资源,将主要资源放在页面渲染实现后加载

留神,随着LCP成为一个更相干的指标,它变得不那么重要了。

4、首次输出延时First Input Delay(FID)[4]

FID掂量的是用户第一次与页面交互到页面真正响应的工夫。注:滚动与缩放不包含在此指标中。延时越长,用户体验越差,最好管制在100ms内。缩小页面初始化工夫,打消长工作能够无效帮忙打消首次输出延时。

计算形式:

能够应用Event Timing API

new PerformanceObserver((entryList) => {  for (const entry of entryList.getEntries()) {    const delay = entry.processingStart - entry.startTime;    console.log('FID candidate:', delay, entry);  }}).observe({type: 'first-input', buffered: true});

还可借助第三方库web-vitals

import { getFID } from 'web-vitals';// 能够发送到监控零碎getFID(console.log);

优化形式:

● 合成长工作● 应用 Web Worker● 缩小JS执行工夫● 优化数据获取● 提早第三方脚本执行● 在SPA中采纳渐进式注水

简略来说,取得更好的FID分数的牢靠策略是将主线程上的工作最小化,办法是将较大的捆绑包分解成较小的捆绑包,并在用户须要时为其提供服务,这样用户交互就不会被提早。

5、累计阻塞时长Total Blocking Time(TBT)[5]

TBT是一个掂量用户事件响应的指标。TBT会统计在FP和TTI工夫之间,主线程被阻塞的工夫总和。当主线程被阻塞超过50ms导致用户事件无奈响应,这样的阻塞时长就会被统计到TBT中。TBT越小阐明页面可能更好的疾速响应用户事件。当页面TBT在300ms内时被认为良好,如果超过600ms则被认为慢了。

计算形式:统计工作超过50ms局部,如下图,3个工作,别离执行了120ms、30ms、75ms,总的TBT是95ms。

优化形式:

● 对JavaScript包进行代码拆分,并提早加载那些对初始加载不重要的包● 在可能的状况下,将代码分解成工作更少、执行更快的函数● 缩小过多的DOM查问● 将计算密集型工作卸载给Service Worker或Web Worker

6、累计布局变动Cumulative Layout Shift (CLS)[6]

CLS是一个掂量页面内容是否稳固的指标,量化了页面加载期间viewport内挪动的元素数量,帮忙确定页面上发生意外挪动的频率。CLS的分数越低,表明页面的布局稳定性越高,通常低于0.1示意页面稳定性良好。

计算形式:CLS = 间隔分数 * 冲击分数

● 间隔分数:不稳固元素挪动的间隔● 冲击分数:受不稳固元素影响的视口表面积

如:元素向下挪动了三分之一的视口高度,所以间隔分数为0.33,元素在初始地位和挪动后占据的区域形成了视口外表的⅔,所以影响分数是0.66。所以,布局移位得分为0.33 × 0.66 = 0.2178。

可应用Layout Instability API

let cls = 0;new PerformanceObserver((entryList) => {  for (const entry of entryList.getEntries()) {    if (!entry.hadRecentInput) {      cls += entry.value;      console.log('Current CLS value:', cls, entry);    }  }}).observe({type: 'layout-shift', buffered: true});

还能够借助第三方库web-vitals

import {getCLS} from 'web-vitals';// Measure and log CLS in all situations// where it needs to be reported.getCLS(console.log);

影响因素:后备字体和web字体有不同的字体指标,或广告,嵌入或iframes来晚了,或图像/视频尺寸没有保留,或早期CSS强制重绘,或更改被早期JavaScript注入。

优化形式:

● img元素:增加宽度和高度属性● 广告:提前定义广告空间的尺寸● 动静内容:应用内容占位符,这样一旦真正的内容加载,布局就不会产生激烈变动● 动画:应用transform属性● 具备font-display: swap属性的web字体:页面布局通常会在web字体加载和替换回退字体时发生变化,因为它们之间的大小不同,要防止这个问题,请应用字体款式匹配器抉择具备类似尺寸的后备字体

7、可交互工夫Time to Interactive(TTI)

TTI度量主线程有5秒没有网络流动或JavaScript长工作的工夫,长工作指耗时超过50ms的JavaScript工作。在这个工夫点上,布局曾经稳固,要害的webfonts是可见的,并且主线线程曾经足够解决用户输出-基本上是用户能够与UI交互的工夫标记。是理解用户在应用站点时要经验多少期待而没有提早的要害指标。它次要标识主线程何时闲暇,而TBT量化主线程在闲暇之前的忙碌水平。

良好的页面性能须要在慢3G中TTI要管制在5s内,二次拜访时TTI管制在2s内。

计算形式:最简略的形式是通过 Performation Api。

const timing = performance.timingconst TTI = timing.loadEventEnd - timing.navigationStart

优化形式:

● 最小化主线程工作● 缩小JavaScript执行工夫

留神:FID和TTI都不思考滚动行为;滚动能够独立产生,因为它是非主线程。

(三)外围Web指标Core Web Vitals[7]

谷歌举荐一系列可承受的速度指标,至多75%的页面浏览量应该超过“良好”范畴,能力通过这个评估。这些指标迅速取得了关注,并在2021年5月成为谷歌搜寻的排名信号

1、LCP < 2.5s on Fast 3G

2、FID < 100ms

3、CLS < 0.1

二、事实指标

(一)响应工夫100ms,每秒60帧

为了让交互感觉晦涩,页面响应用户的输出动作最好小于100ms。

为了达到<100毫秒的响应工夫,页面必须每隔<50毫秒将控制权交还给主线程。输出提早能够通知咱们是否达到该阈值,现实状况下,它应该低于50ms。对于像动画这样的敏感点,最好在你执行动画的时候什么都不做。

另外,动画的每一帧都应在16毫秒内实现,从而达到每秒60帧(1秒÷60 = 16.6毫秒)- 因为浏览器须要工夫能力在屏幕上绘制新的帧,而你的代码应在16.6毫秒之前实现执行,所以最好在10毫秒以内。

(二)3G环境下 FID < 100ms, LCP < 2.5s, TTI < 5s,要害文件大小 < 170KB (gzip压缩后)

尽管很难实现,但一个好的指标是将TTI管制在5s内,二次拜访时,将TTI管制在2s内。LCP的指标是2.5s以下,同时最大限度地缩小TBT和CLS。一个能够接管的FID须要管制在100-70ms内。

为了网络疾速传输内容,有2个限度因素。一方面因为TCP慢启动,咱们受网络传输限度:HTML的前14KB是最要害的无效传输块,并且是内容中惟一能够在第一次网络往返就传输实现的局部( 加上挪动网络唤醒工夫的起因,这就是您在RTT为400ms网络的环境下在1s内能取得的最多内容)。另一方面,因为JavaScript解析须要工夫,咱们在内存和CPU方面存在硬件限度,为了实现咱们的指标,必须思考JS要害文件大小,压缩到170KB JavaScript的文件曾经须要破费了1s能力在一般手机上进行解析和编译。假如170KB的文件在解压缩时扩大到原来的3倍(0.7MB),那在Moto G4 / G5 Plus上这类机型上就曾经很大达到“体面的”用户体验了。针对懒加载路由,Addy Osmani也倡议管制在35KB以内。

注:为什么是14KB?当TCP启动时,它容许发送10个TCP包,而后它们必须被确认。当这些数据包被确认后,它就容许发送更多的数据包,加倍后容许下一次发送20个数据包,而后是40个,而后是80个……随着它逐步建设到网络能够解决的全副容量。14kb的神奇数字是因为每个TCP包最多能够有1500个字节,然而其中40个字节是留给TCP应用的(TCP头等),剩下1460个字节留给理论数据。其中的10个数据包意味着您能够交付14600字节或大概14kb(实际上是14.25 KB)。当然,这都是实践上的,理论如何有趣味的能够浏览博客[8]。

三、抉择设施

为了收集精确的数据,咱们须要彻底全面地抉择要测试的设施。

依据IDC的数据,到2020年,寰球84.8%的手机出货量为Android设施。一般消费者每两年更换一次手机,而美国的手机更换周期是33个月。寰球最滞销手机的均匀售价不到200美元。

那么,一个代表性的设施,是一个Android设施,至多用了24个月,价格为200美元或更少,运行在迟缓的3G, 400ms RTT和400kbps传输。当然,这比拟乐观了。尽管这可能是合乎大部分的用户,但咱们还是要以公司理论的客户为准。

针对以上状况,在开放式设施实验室中,咱们能够抉择稍老一点的Moto G4/G5 Plus,中档三星设施(Galaxy A50, S8),不错的中档设施,如Nexus 5X,小米Mi A3或小米红米Note 7,以及速度较慢的设施,如阿尔卡特1X或Cubot X19。如果你想在较慢的热调节设施上测试,你也能够买一台Nexus 4,价格仅为100美元左右。

此外,查看每个设施应用的芯片组,机型组合不要适度集中在一个芯片组中: 倡议蕴含几代的骁龙CPU(Snapdragon)和苹果CPU(Apple)以及低端的Rockchip、联发科(Mediatek)

如果您手头没有设施,能够先在在台式机上模仿挪动体验:节流的3G网络(例如300ms RTT、1.6 Mbps上行、0.8 Mbps上行)和CPU限速(加速5倍)上进行测试。最终切换到惯例3G、低速4G(例如170ms RTT、9 Mbps上行、9 Mbps上行)和Wi-Fi。

四、抉择环境

(一)构建工具

不要过于关注那些被认为很酷的工具,保持在你的开发流程中进行构建优化,无论是Grunt、Gulp、Webpack、Parcel还是这些工具的组合。只有取得了想要的后果,并且保护构建过程没有问题,那就足够了。

在所有构建工具中,Rollup一直取得关注,Snowpack也一样,但Webpack仿佛是最成熟的一个,它有数百个插件可用来优化构建的大小。查看Webpack 2021路线图。如果想理解更多Webpack,能够浏览原文,提供了一系列学习资源。

(二)框架

因为有十分多的未知因素影响加载性能-网络、负载平衡、缓存笼罩、第三方脚本、解析器阻塞模式、磁盘I/O、IPC提早、装置的扩大、防病毒软件和防火墙、后盾CPU工作、硬件和内存限度、二级/三级缓存的差别、RTTS。JavaScript是其中影响最多、老本最高的,仅次于默认状况下阻止页面出现的Web字体和常常耗费太多内存的图像。

之前提到的170KB的估算曾经蕴含要害门路HTML/CSS/JavaScript、路由器、状态治理、实用程序、框架和利用程序逻辑,所以咱们必须彻底查看咱们抉择的框架的网络传输老本、解析/编译工夫和运行时老本。

当初,不是每个web利用都须要前端框架,在单页应用程序中也不是每个页面都须要加载框架。在Netflix的场景中,“从客户端删除React,一些第三方库和相应的利用程序代码能够将JavaScript的总量缩小200KB以上,从而使Netflix首页登录的可互动工夫缩小了50%以上。”而后,该团队利用用户在登录页面上破费的工夫来预取React,这样做在用户可能拜访的后续页面中就不必持续加载React了。

一旦抉择好了框架,咱们通常会至多应用几年,所以肯定要确保咱们的抉择是理解并通过三思而行的。

数据表明,框架自身就相当低廉:58.6% 的React 页面JavaScript超过1 MB, 36% 的Vue.js 页面加载FCP小于1.5s。依据Ankur Sethi钻研后果:"在印度,React应用程序无论你怎么优化,在一般手机上加载速度都不可能超过1.1s,Angular应用程序须要花至多2.7s能力实现启动,Vue应用程序须要用户至多期待1s能力开始应用。尽管印度并非你的次要市场,然而应用次优网络增加拜访你网站的用户会有相似的体验。

如果抉择框架?至多要思考框架的大小以及框架的初始执行工夫。Seb Markbège指出,掂量框架启动老本的一个好办法是先渲染视图,而后删除视图再二次渲染,这样就能够晓得框架绘制的老本。因而首次渲染视图之前往往须要预热一堆提早编译的代码,更大DOM树在绘制时受害更多。二次渲染则是模仿页面上的代码复用度是如何随着页面复杂度的减少而影响性能特色。

Sacha Greif的12分制评分零碎[9]也可帮忙你评估一个框架(或任何JavaScript库)包含:摸索个性、可拜访性、稳定性、性能、包生态系统、社区、学习曲线、文档、工具、跟踪记录、团队、兼容性、安全性等。还能够依赖Perf Track[10],长期大规模跟踪框架性能,收集Angular,React,Vue,Polymer,Preact,Ember,Svelte和AMP在构建的网站的原始汇总的Core Web Vitals分数。

(三)渲染形式[11]

最终的办法是设置某种渐进式疏导:应用服务端渲染来取得一个疾速的FCP,但也包含一些必要的JS来放弃TTI靠近FCP。如果JS在FCP之后呈现得太晚,浏览器将在解析、编译和执行迟发现的JS时锁定主线程,从而限度站点或应用程序的交互性。为了防止此类问题产生,将工作划分为独立、异步的,能够思考应用import()动静加载的形式,只有在用户真正须要时才去加载、解析、编译。

对于渲染形式,咱们有几种抉择:

● Full Server-Side Rendering (SSR)

所有申请都在服务器上实现。相似以前的JSP、PHP。

长处:申请的内容作为实现的HTML页面返回,浏览器能够立刻出现它。因为HTML是流到浏览器,FCP和TTI之间的差距通常很小。因为它是在浏览器取得响应之前解决的,同时防止了客户端数据获取和模板的额定往返。

毛病:SSR应用程序不能真正利用DOM API;服务器响应工夫较长,没有利用古代应用程序的响应性和丰盛的个性。

● Static Rendering

构建时产生,单页应用程序,所有页面都事后出现为动态HTML,构建步骤中应用起码的JS。

长处:页面的HTML不须要动静生成,服务器响应工夫快,能够疾速获取第一个字节。

毛病:必须为每个可能的URL生成独自的HTML文件。当你无奈提前预测是哪些URL时或用于具备大量独特页面的站点时,这可能具备挑战性,甚至是不可行的。

● Server-Side Rendering With (Re)Hydration (Universal Rendering, SSR + CSR)

一次出现多个申请,将生成内容时以块的模式发送内容。(服务器将应用程序出现为HTML,而后在客户端上申请JavaScript和用于出现的数据再次渲染来“修补” 。)

长处:取得客户端利用的齐全灵活性,同时提供更快的服务器端渲染,改良了First Paint。因为应用了SSR,所有也有其长处,实现疾速的FCP。

毛病:FCP与TTI之间产生更长的距离,同时减少了FID。SSR的页面通常看起来具备欺骗性,在执行客户端JS并附加事件处理程序之前,无奈响应输出。

● Streaming Server-Side Rendering With Progressive Hydration (SSR + CSR)

与上一个相似,内容以流式模式生成并发送。

长处:不用期待残缺的HTML字符串后再将内容发送到浏览器,因而改良了Time to First Byte。在客户端,采纳逐渐启动组件,缩小FID与TTI,同时放大FCP与TTI间接的距离。

● Trisomorphic Rendering

为初始/非js导航提供流服务器渲染,而后让service worker在装置后为导航提供HTML渲染。

● CSR With Prerendering

预渲染相似于服务器端出现,但不是在服务器上动静出现页面,而是在构建时将应用程序渲染为动态HTML。它在构建时将客户端应用程序的初始状态捕捉为动态HTML,而预渲染应用程序必须在客户端上启动,以便页面是交互式的。

长处:更好的Time To First Byte和FCP,缩小了TTI和FCP之间的差距。

毛病:如果预期内容会有很大变动,咱们就不能应用这种办法。另外,必须提前晓得所有url能力生成所有页面。

● Full Client-Side Rendering (CSR)

应用JavaScript在浏览器中间接渲染页面。所有逻辑,数据获取,模板和路由都在客户端而不是服务器上解决。

毛病:TTI与FCP差距较大。因为整个应用程序必须在客户端上启动能力出现内容,所以整个应用程序会比较慢。随着应用程序的增长,所需的JavaScript数量趋于增长。

总的来说,SSR比CSR要快,仅仅只是SSR,或仅仅只是CSR都不是一个好的形式,最好是联合两者。如果您的页面变动不大,请思考预渲染,并尽可能推延框架的启动。应用服务器端出现的HTML块流,并为客户端出现实现循序渐进的水化——并在可见性、交互或闲暇工夫水化,以取得两者的最佳成果。

当然,如果能够,咱们还是须要尽可能的动态化,提前预构建更多的内容,而不是在申请时在服务器或客户端上生成页面视图,咱们将取得更好的性能。

另外,还能够思考应用PRPL模式和骨架屏,其想法非常简单:将实现初始路由交互所需的最小代码推入,以便疾速出现,而后应用service worker缓存和预缓存资源,而后异步地惰性加载所需的路由。

(四)其余

1、尽可能的从CDN动态提供内容

咱们事后构建的内容越多,而不是在申请时在服务器或客户端上生成页面视图,咱们将取得更好的性能。

2、思考应用PRPL模式和App Shell架构

PRPL模式[12]

它形容一种用于使网页加载并变得交互式,更快的模式:

● 推送(或预加载)最重要的资源。● 尽快渲染初始路线。● 预缓存残余资产。● 提早加载其余路由和非关键资产。

App Shell 架构[13]

是反对用户界面的最小HTML,CSS和JavaScript。App Shell架构应:

● 疾速加载● 被缓存● 动态显示内容

3、优化API的性能

GraphQL[14]是API的一种查询语言,并且是服务器端运行时的,用于通过应用为数据定义的类型零碎执行查问。与REST不同,GraphQL能够在单个申请中检索所有数据,并且只响应所需的内容,而不会像REST通常那样适度或有余地获取数据。

此外,因为GraphQL应用模式(schema,定义数据结构的元数据),所以它能够提前将数据组织成所需的构造,因而应用GraphQL,咱们能够删除用于解决状态和数据后果的JavaScript代码,从而产生在客户端上运行更快更洁净的利用程序代码。

4、应用AMP还是Instant Articles?

AMP[15]:是一个Web组件框架,可轻松为Web创立用户至上的体验。

Instant Article[16]:一种原生格局,可供发行商创立加载迅速的 Facebook 互动式文章。

Apple News[17]: 是业余新闻出版物的平台。

5、正当抉择CDN

仔细检查你的CDN是否反对执行压缩和转换(例如,图像优化和调整大小),是否为Service Worker提供反对,A/B测试,将在CDN层面组合页面的动态和动静局部(间隔用户最近的服务器)以及其余反对的个性。此外,查看你的CDN是否反对HTTP over QUIC(HTTP/3)。

如何抉择CDN,能够参考Katie Hempenius对于CDN的领导[18]。通常,最好是尽可能踊跃地缓存内容并启用CDN性能性能(如Brotli,TLS 1.3,HTTP / 2和HTTP / 3)。原文还有很多对于CDN比拟的网站,有趣味的也能够看一下。

欢送关注我的集体公众号:

参考资料

Front-End Performance Checklist 2021[1]:https://www.smashingmagazine....
Why Perceived Performance Matters, Part 1: The Perception Of Time[2]:https://www.smashingmagazine....
Largest Contentful Paint (LCP)[3]:https://web.dev/lcp/
First Input Delay[4]:https://web.dev/fid/
Total Blocking Time (TBT) [5]:https://web.dev/tbt/
Cumulative Layout Shift (CLS)[6]:https://web.dev/cls/
Web Vitals[7]:https://web.dev/vitals/
web-vitals library:https://github.com/GoogleChro...
Optimize for Core Web Vitals:https://www.youtube.com/watch...
Critical Resources and the First 14 KB[8]:https://www.tunetheweb.com/bl...
12-point scale scoring system[9]:https://www.freecodecamp.org/...
Perf Track[10]:https://perf-track.web.app/
Rendering on the Web[11]:https://developers.google.com...
PRPL pattern[12]:https://web.dev/apply-instant...
App shell architecture[13]:https://developers.google.com...
GraphQL[14]:https://graphql.org/
AMP[15]:https://amp.dev/
Instant Articles[16]:https://www.facebook.com/form...
Apple News[17]:https://developer.apple.com/n...
Content delivery networks (CDNs)[18]:https://web.dev/content-deliv...