如何加快SPA的速度

单页面应用程序(SPA)可能要花很长时间才能发射。这是一个巨大的问题,因为即使延迟一秒钟也会使您花费7%的转化。

但是就像您可以使单页应用程序对SEO友好一样,您也可以提高其性能。

因此,这是我们的详细指南,针对那些希望在2020年加速SPA应用程序的人。对于那些不熟悉SPA概念的人,我建议从我们的文章开始,内容是什么是单页应用程序以及它们与传统多页应用程序的比较页应用程序。

监控您的SPA效果

有很多工具可以帮助您监视SPA性能。首先,您可以使用Chrome Devtools扩展,例如LighthouseEmber InspectorReact Performance Devtools

此类工具的问题在于它们不能反映出您的SPA的感知加载速度(这对用户来说很重要)。

还有诸如速度索引之类的其他工具集,它们试图匹配实际的用户体验。

但是实际用户来自各种各样的设备/网络,因此很难在综合测试环境中考虑所有这些因素。

我们建议您使用真实用户监视(RUM)。它被动地跟踪人们与您的应用程序的每次交互,从而为您提供有关用户如何感知其加载速度的准确实时图像。

如果您喜欢现成的解决方案,那么这里是一些支持单页应用程序的RUM工具的简短列表:

您还可以要求您的开发团队将RUM应用于SPA。

它必须识别连续导航的开始(又称导航/页面内导航:应用启动后,用户单击指向SPA中新“页面”的链接/按钮)以及页面完全被载入那一刻。已加载。开发人员可以通过几种方式实现此目的:

  • 使用Resource Timing API识别何时进行AJAX调用以查明页内导航的开始;
  • 使用Mutation Observer可以检测到对DOM的修改,并通过Resource Timing API识别网络活动的结束。

实践表明,这些方法可能不可靠,并且结果不准确。例如,即使用户不启动页内导航,您的SPA也会调用AJAX来预取一些数据。否则结果可能会因网络活动而歪曲,而不会影响屏幕上发生的事情。

为了解决这个问题,他们可以使用简单的API来衡量加载时间:

var rumObj = new RumTracking({
  'web-ui-framework': 'EMBER'
});
 
// App Launch - window.performance.timing.navigationStart is the start marker
rumObj.setPageKey('feed_page_key');
// Do rendering
rumObj.appRenderComplete();
 
// Successive navigation
rumObj.appTransitionStart();
rumObj.setPageKey('profile_page_key');
// Do rendering
rumObj.appRenderComplete();

使用这种方法,每个页面都必须编写检测代码。

许多单页应用程序JavaScript框架都有生命周期hooks ,可用于自动执行检测。

// Add instrumentation for successive navigation start
router.on('willTransition', () => {
 a. rumObj.appTransitionStart();
});
 
// Add instrumentation for rendering is complete
router.on('didTransition', () => {
Ember.run.scheduleOnce('afterRender', () => {
 a. rumObj.appRenderComplete();
   });
});

因此,开发人员可以使用Navigation Timing API的导航开始来检测初始导航的开始。路由器的willTransition事件将标志着页面内导航的开始。

通过监听еруdidTransition事件并在afterRender队列中添加工作,您将知道两种模式下页面的完全加载时间。

现在,您已经拥有测量加载时间所需的一切。要发现性能瓶颈,您需要细分RUM数据。您可以通过User Timing API检测单个资源的加载时间。

典型的SPA的性能瀑布外观

现在是时候分析RUM数据,看看可以如何解决瓶颈了。

改善SPA性能的六大方法

1.懒惰地呈现折叠式内容

简而言之,这意味着仅呈现页面上当前对用户可见的那些部分(即首屏内容)。

如果您的SPA在渲染阶段花费大量时间(请参见上图),则惰性渲染很有用。在此阶段,应用程序将为页面上的所有组件创建DOM(有关如何在页面上表示文本,图像和其他对象的规范)。

一旦为首个组件构建了DOM,就可以产生浏览器的主线程。这将加快SPA的启动速度,因为您不必呈现当前不需要的资源。

将渲染优先级分配给页面上的所有组件可能会带来另一个性能提升(因此浏览器不会同时渲染所有组件)。

这样,您可以加快“第一个有意义的画图”(即用户看到页面核心内容的时间)。通过不渲染某些不可见的组件,您还将改善“互动时间”

2.使用延迟数据获取

加快渲染阶段之后,您可能需要研究过渡阶段。

此时,SPA加载数据,对其进行规范化并将其推送到存储中。为了减少在此阶段花费的时间,您需要减少SPA处理的数据量。

正如您可以懒惰地呈现折叠式内容一样,您可以推迟加载数据,直到真正需要它为止。

您可以使用一个高级调用来获取“第一有意义绘画”所需的数据,而可以使用另一个调用来懒惰地加载页面所需的其余数据。

注意:上述方法适用于启动模式和页内导航,因为它们减少了前端时间。

一些SPA框架(例如React,Angular或Vue)允许开发人员将应用程序代码分成几个捆绑包。您可以同时或在必要时加载它们。第二个选项可以加快第一个导航的速度。例如,您可以仅加载用户可以立即访问的部件,而推迟其他所有操作(例如,需要授权的部件)。

3.缓存静态内容

研究您的SPA,以确定何时可以在用户设备上存储图像和其他静态资源。

即使使用最佳服务器,从内存或Web存储中提取数据所需的时间也比发送HTTP请求少得多。

设备内存比最快的网络快得多。因此,缓存是您最好的朋友。

对于大量集合,您可以使用某种分页并依靠服务器来保持持久性,或者编写LRU算法来从存储中擦除备用项。

您可以使用Service Worker在SPA中缓存静态内容。

它们是在后台运行的客户端脚本。您可以使用它们来减少流量并启用脱机功能。当浏览器请求内容时,它首先经过服务人员。如果请求的内容存在于缓存中,则服务工作者将检索它并显示在屏幕上。在其他情况下,它将从网络请求资源。

您还可以使用IndexedDB API缓存大量结构化数据。

4.在适当的地方使用WebSockets(即用于高度交互的应用程序)

WebSocket是允许用户浏览器和服务器之间进行双向通信的协议。与HTTP不同,客户端不必不断向服务器发送请求以获取新消息。取而代之的是,浏览器仅侦听服务器并在就绪时接收消息。

结果,您得到的连接在某些情况下可以比常规HTTP快400%

您可以使用socket.io之类的服务为SPA实现WebSockets。

5.使用JSONP / CORS绕过同源策略

许多应用程序的某些功能都依赖于第三方API。

但是由于同源策略,您无法对浏览器认为位于另一台服务器上的页面进行AJAX调用。要获得对第三方API的访问权限,该应用将必须使用源服务器作为代理。

额外的往返意味着更多的延迟。


如果不处理检索到的数据并且不将其存储在系统中,则可以直接请求资源。为此,您可以使用带有填充的JSON(JSONP)或跨域资源共享(CORS)

JSON with Padding

JSONP充分利用了浏览器允许您添加来自其他域的<script>标签的事实。通过JSONP请求,您可以动态构造这些标签,并将URL参数传递给必要的资源。

然后,标记会在JSON响应中返回资源。

但是有一个缺点。使用<script>标记时,JSONP仅适用于<GET>请求。您可以通过将async和defer属性添加到外部脚本来进一步提高性能。如果没有这些属性,浏览器必须先下载并执行脚本,然后才能显示页面的其余部分。

这减慢了感知的加载速度。

如果包含async属性,则浏览器在加载脚本时不会停止解析页面,但是在执行脚本时仍会暂停解析。该延迟属性,另一方面,直到页面完全解析延迟脚本执行

跨域资源共享

CORS允许您定义可以访问服务器内容的人员和方式。

但是有一个问题。使用除GET,HEAD和POST之外的任何方法的请求将启动预检检查,以确认服务器已准备好进行跨域请求。

为了运行检查,客户端发送另一个请求,该请求描述了跨域AJAX调用的来源,方法和标头。根据此信息,服务器决定是否处理该呼叫。客户端收到响应后,将启动对第三方资源的请求。

preflight检查增加了第二次往返,因此可以有效地将您的延迟加倍。


preflight checks

您可以使用以下方法之一来处理预检请求:

1.编写API并仅使用HEAD,GET,POST,Accept,Accept-Language,Content-Language和Content-Type来提供内容,因为它们不会启动预检请求。

在接受头使您能够定义可接受的内容类型的能力。默认情况下,首选类型为text / html,但是您可以将application / json或任何其他类型的内容作为唯一的可接受类型。然后,您的后端将检查Accept标头,然后选择发送HTML,JSON或其他响应。

2.缓存预检响应以减少后续检查。

在这种情况下,您不能依靠通常的Cache-Control标头来定义缓存策略。但是您可以改用新的Access-Control-Max-Age标头。其数值定义了缓存响应所需的秒数。

6.使用内容传送网络(CDN)

CDN是遍布全球的服务器网络。您可以使用CDN以更有效的方式传递静态资源(如图像)。网络中的每个服务器都包含原始服务器上托管的内容的缓存版本。

如果来自墨尔本的用户请求图像,则网络将不会从位于纽约的原始服务器获取图像。CDN将使用澳大利亚服务器(或等待时间最少的备用服务器)来提供缓存的内容。

对单页应用程序使用CDN意味着更快地加载脚本并减少了交互时间。增加安全性是一个不错的奖励。


结论说明

这些是我们加快单页应用程序速度的6种方法。

这是一个奖励:测量优化重复(但仅在需要时)。

此建议适用于任何应用程序,因为优化是一个连续的过程。

您对代码所做的每次更改都会影响页面加载速度。因此,请评估您的SPA的行为,并避免过早的优化,因为开发人员会花费大量时间来调整其应用程序中不必要的部分。

参考

How to speed-up your Single-Page Application

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容

  • 一年前写了一篇JavaScript八张思维导图,主要是对前端JavaScript知识点的一个系统的整理和总结。本篇...
    dykingdy阅读 1,778评论 0 0
  • 前后端分离算是最近Web开发的大趋势了,目前已经有大量的公司使用了前后端分离的开发方式。那我们就来大概谈谈前后端分...
    程点阅读 37,262评论 13 108
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 夜莺2517阅读 127,717评论 1 9
  • 版本:ios 1.2.1 亮点: 1.app角标可以实时更新天气温度或选择空气质量,建议处女座就不要选了,不然老想...
    我就是沉沉阅读 6,887评论 1 6