Skip to content

极致PCWeb性能 —— 静态化&工程化JSONP #13

Description

@yesvods

在大家的认知里,JSONP,往往是另外一种异步请求的方式,其主要优点是支持跨域数据请求。因此,JSONP往往是将一个Script节点动态插入document,随后浏览器会自动发起一个远程请求。

除了上述单一用法外,在PCWeb,JSONP具有非常巨大的性能&工程化价值。

1.异步JSONP

通过【图说舌尖上的脚本】与【同步vs异步加载】了解到,PCWeb受限于插件环境,异步机制变得非常不吃香。异步发起的请求,无论是JSONP等资源加载,抑或XHR(fetch),都会被标记为低优先级。

  • 同步插件脚本加载完才能发起请求
  • 在主进程的编译与执行前,会被插件脚本抢占。

我们来看一下,发起6个异步JSONP是怎样的情况:

<script>
function appendScript(src){
 var s = document.createElement('script')
 s.src = src
 document.body.appendChild(s)
}
for(let i=0;i<6;i++){
 appendScript(`./react.js?v=${i}`)
}
</script>

结果跟之前分析的异步请求别无二致,异步JSONP默默低下了头。

2.同步JSONP —— 将页面加载性能发挥极致

2-1. 现实中的场景

举个栗子,在实际PC场景,无论采用的是React Or Vue Or what ever. 我们都需要在渲染前加载一堆组件,数据+模板(JSX etc.)+组件方式,来实现渲染。我们在渲染页面前就需要加载一堆资源,有时候甚至可以达到2M之大!

2-2. 性能分析

这块大资源并没有错(有时候利用一块大资源,比起每次加载不一样非缓存资源性能还高),但是在浏览器加载这块大头时候,脚本的解析、编译、执行,也随着体积增长(特别是执行耗时)。当然,这也有一些办法可以减轻这些负担(未完,待续..)。然而,我们可以利用上面介绍到的同步JSONP优雅地减少页面加载时间!我们先来回顾一下部分原理:

因为主线程被阻碍了,后面的解析工作没有办法继续往下进行,
当遇到这种情况,WebKit会启动另外一个线程去遍历后面的HTML,
收集需要的资源URL,然后发送请求,这样就可以避免阻塞。 
	———— 《WebKit技术内幕》

2-3. 优雅技术方案

我们把资源都看成一个大体积Bundle,在HTML解析到这个脚本时,由于无需下载(memory cached Or disk cached),接下来就是漫长的解析、编译、执行。但是,我们可不能让浏览器闲着,通过同步JSONP,在Bundle后面声明一堆以后渲染要用的页面数据。这样,浏览器主进程漫长的阻塞执行过程中,相关的数据已经被网络模块准备就绪,由于模块数据相对体积小,因此没有解析/编译/执行成本。

<script src="BigBundle.js"></script>
<script src="parallelData1.js"></script>
<script src="parallelData2.js"></script>
<script src="parallelData3.js"></script>
<script src="parallelData4.js"></script>
<script src="parallelData5.js"></script>
<script src="parallelData6.js"></script>

我们一直提到的是,在PCWeb页面初始化场景,异步加载都会面临性能问题。而上述的方案通过所有资源同步的方式实现,用最高优先级来渲染初始页。

2-3. 真实的故事

在鄙人的某些业务场景下,真实用到同步加载Bundle,异步获取资源,首屏渲染时间惨不忍睹。仅仅通过资源JSONP同步化,还没做其他优化😕,首屏时间直接从2.1s,下降至1.4s😱。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions