Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
yesvods opened this issue Jun 24, 2017 · 4 comments
Open

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

yesvods opened this issue Jun 24, 2017 · 4 comments

Comments

@yesvods
Copy link
Owner

yesvods commented Jun 24, 2017

在大家的认知里,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😱。

@iFwu
Copy link

iFwu commented Jun 25, 2017

有相应的打包方案吗?数据怎么与脚本分离?

@yesvods
Copy link
Owner Author

yesvods commented Jun 25, 2017

@xekri 工程化方案有很多种,之后会介绍其中一种方式,但是不能覆盖所有应用场景。特定场景,特定工程化应用,原理都是一致的。

@broadviewcheemi
Copy link

博主您好,我是电子工业出版社博文视点的编辑,您的《极致PCWeb性能》系列内容很好,请问您是否有兴趣出版前端方面的图书呢:)

@broadviewcheemi
Copy link

broadviewcheemi commented Jun 30, 2017 via email

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

No branches or pull requests

3 participants