【皇家赌场手机版】白屏题材和FOUC,页面可知时间与异步加载

页面白屏与瀑布流分析方法

2015/12/03 · HTML5,
JavaScript · 1
评论 ·
瀑布流,
白屏

初稿出处: 天猫商城前端团队(FED)-
妙净   

皇家赌场手机版 1

有线页面包车型大巴开发在大家的常见工作中进一步主要,有线的属性也是咱们需求重点关心的,而加载的品质又是有线质量中的二个重大难点。那么,前几天大家联合来看下怎么样去评估、测试无线页面包车型大巴加载品质。

为了便利分析页面包车型大巴加载进程,那里将互连网设置成最慢的
GPLANDS,并将加载进程录制下来,平时你能够透过 Chrome 自带的 timeline, 勾选
screenhot,能够拿走详尽的进程,如下图:

皇家赌场手机版 2

此处为了和伸手一一清晰对照,用额外录屏工具( licecap
)录像下来。下文以Tmall双 11 男装分会场的预发页面作为测试,摄像 结果
gif
如下,录制的 FPS 为 8。

帧分析如下:

第叁帧:重新刷新页面,发起 HTML 请求,中间完整页面是刷新前的,请无视之。

皇家赌场手机版 3

算是等到第 7 帧,HTML 加载并分析达成,发出页面中的请求,同时 CSS/JS
的地点都冰释在 //g.alicdn.com 同二个域名下, Chrome 下 HTTP 1.1
协议下2个域名下扶助 6 个冒出。

1 年前,PC 上从前还有七个域名分区(img01-04.tbcdn.cn),PC
上首屏图片多,那样可并发愈来愈多,但越多的域名引入,也加大了域名解析的成本,权衡之下Tmall此前图片域名采纳了
4 个;后来集团通过轰轰烈烈的 HTTPS 改造,图片推荐收敛到 gw.alicdn.com
;手淘下以往选择 SPDY + HTTPS,比较 HTTP 1.1 ,更安全且能够多路复用。

皇家赌场手机版 4

到第 20 帧, CSS 下载完,DOM 和
CSSOM
都准备 OK 了,页面则开头渲染了;那是在 Chrome 下边看看的图景,但在 iOS
上并非如此,它须要 JS 加载并施行完才渲染页面。

皇家赌场手机版 5

第 21 帧,紧接着,CSS 中的背景图发轫相继渲染,可知 CSS
中渲染图片也是有点耗费时间的。

皇家赌场手机版 6

第 23 帧,前边并行下载的 JS 都下载完,也开始执行了,看“疯狂 top 榜”是 JS
抽取出来的。同时 aplus 请求也开头请求,那是个 getScript
的异步请求,可知异步请求真没有阻塞页面包车型客车渲染。

皇家赌场手机版 7

第 25 帧,JS 还在继续执行,第壹张图片是 JS 依照当前
dpr、强弱网络、设备宽度等算出最契合的图纸初始加载那张大 banner
了,并且开头发送数据请求了。

皇家赌场手机版 8

到 27 帧,终于数据请求回来了,并且把文字和图表渲染到页面上了。

皇家赌场手机版 9

接下来下一帧 28,起初请求商品图片了。

皇家赌场手机版 10

到 45 帧,6 个图片都在产出请求,同上 gw.alicdn.com 同1个域下并发 伍个请求。但首屏除了大图外唯有 4 张图(2 张商行 logo 被尾部 bar
挡住了),那里产生了 6 个图片请求,可知这一个页面的懒加载的 buffer
值能够设置得更小。

皇家赌场手机版 11

从 28 帧到 50 帧,经历了很短的大运,第壹张图纸终于显示出来了。另外看到
aplus_v2 执行完后,又发起了 spm 等请求,前面 3 个请求(
aplus-proxy.html/isproxy.js/m.gif )依然串行的。

皇家赌场手机版 12

【皇家赌场手机版】白屏题材和FOUC,页面可知时间与异步加载。终极到第 61 帧,终于有所的图片都加载完了,最后看下,最后下载完的是大
banner 图,因为有 46.9k ,那张图的分寸大概成为此页面包车型地铁 load
时间的第2;假如那张图没有这么大,最终下载完的或然是用以埋点的 m.gif。

皇家赌场手机版 13

从上面整个请求的瀑布流分析下来,大家来回想下页面包车型地铁关键时刻点:

初稿出处: Taobao前端团队(FED)-
妙净   

白屏难题

  1. 白屏的根本原因是浏览器在渲染的时候没有请求到或请求时间过长造成的。
  2. 浏览器对于图片和CSS,在加载时会并发加载(比如叁个域名下同时加载七个文本),浏览器对于JavaScript,在加载时会禁止使用并发,并且阻止其后的公文及零部件的下载。所以将js放在页面包车型客车顶部也或然会招致白屏。
  3. 不等浏览器的拍卖CSS和HTML的法门是见仁见智的:
    比如,IE、chrome浏览器的渲染机制,接纳的是等CSS全体加载解析完后再渲染体现页面。
    Firefox则是在CSS未加载前先出示html的内容,等CSS加载后再也对体制进行改动。

【皇家赌场手机版】白屏题材和FOUC,页面可知时间与异步加载。据此:白屏的产出意况屡屡因为CSS样式被平放底部(最终加载),当新窗口打开,刷新等的时候,页面会现出白屏。
若果运用
@import标签,它引用的文本则会等页面全体下载实现再被加载,也说不定出现白屏。

因此,
css使用 link 标签将样式表放在顶部,防止白屏难题应运而生。
JS 的停放地方一般是在body的密闭标签以前。

CSS和JS在HTML中的地方

诚如CSS放在head里用<style></style>包裹,或用link标签引入css文件
JS因为浏览器渲染机制会放在底部</body>
以前,就是在加载渲染完HTML、CSS后在加载JS,不受白屏影响;假设用link标签引入则供给defer/async让其异步使页面不受白屏影响

页面可知时间

在第 20 帧页面可知,CSS 完毕今后,当然前提是此处没有外链 JS
在页面中间因为互连网请求严重阻塞页面。那里分析的可是是 Chrome
浏览器,不是真机,在 iOS 上,就算 JS 在底部,直接 <script src=”xx”> 也是会阻塞页面。能够经过加
async 属性,布告渲染引擎那是不影响页面渲染的 JS,可以异步加载,iOS
下添加此属性可实现和 Android 或 PC Chrome 一样的职能。

皇家赌场手机版 14

白屏不是bug,而是由于浏览器的渲染机制。
白屏和FOUC
  • 万一把体制放在底部,对于IE浏览器,在好几场景下(新窗口打开,刷新等)页面会产出白屏,而不是内容日益显示;如若用
    @import 标签,尽管CSS放入link,并且位居头顶,也大概出现白屏
    白屏是因为浏览器的渲染机制,浏览器渲染的时候请求时间过长导致白屏,chrome的渲染流程:html >
    Dom > css > Cssom > Render Tree > Layout >
    Painting,可以看看是终极才会layout然后再painting,所以浏览器页面在css加载渲染完领悟后才会有内容呈现,若是浏览部分海外的网站,网站被墙,浏览器会从来呈现loding而没有页面突显,就是因为网页响应时间过长导致白屏;当使用@import()时,属性或许造成浏览器渲染不立时,又或许大家把标签放在了body的底层地点,都恐怕引致不立即的场合。所以一般用link标签把css样式文件引入并放置在head里
  • FOUC(Flash Of Unstyled
    Content)无样式内容闪烁:假设把体制放在尾部,对于IE浏览器在有些场景下(点击链接,输入U宝马X3L,使用书签进入等)会并发ROUC现象(稳步加载无样式的剧情,等CSS加载后页面突然表现样式)对于Firefox会一直展现出FOUC
    FireFox的渲染逻辑和Chrome的不太雷同,一起始Chrome是等待渲染树和岗位总括好才会出来网页的内容,但到了FireFox每加载三次dom树就会重绘一次网页样式,平素到具有内容完毕收尾,所以一般大家用link把css放在header内

重庆大学内容可知时间

关键内容可知,那里能够认为是商品数量,商品数量可知要等 JS
执行完并且异步请求发送出去回来后才可见。

TMS\[1\]
的异步请求大多走招商数据平台(TCE\[2\])的接口,测试其单个请求在真机的耗费时间约为
110ms(样本较少,未大批量测试)。

怎样让页面尽只怕早地渲染页面,页面更早可见,让白屏时间更短,尤其是有线环境下,一直是性质优化的话题。

FOUC

FOUC (Flash of Unstyled Content) 无样式内容闪烁:
假若把体制放在底部,对于IE浏览器,在少数场景下(点击链接,输入UTiguanL,使用书签进入等),会油可是生
FOUC 现象(稳步加载无样式的内容,等CSS加载后页面才赫然突显出样式)。对于
Firefox 会一贯呈现出 FOUC 。

  • 脚本会阻塞后边内容的显现
  • 脚本会阻塞其后组件的下载

对此图片和CSS,
在加载时会并发加载(如3个域归属同时加载几个公文)。但在加载 JavaScript
时,会禁止使用并发,并且阻止其余内容的下载。

所以尽大概把 JavaScript 放入页面body底部。

async和defer

js对页面加载和渲染有多个影响:阻塞后面内容的表现和封堵其后组件的下载,是因为浏览器的渲染机制:对于图片和css,在加载时会并发加载(如三个域名下同时加载三个公文)但在加载JavaScript时会禁止使用并发,并阻挠别的内容的下载。所以把JavaScript放入页面顶部也会造成白屏现象
当用link标签在head里引入.js文件则要求用async和defer来异步
async:加载渲染后续文书档案元素的历程和.js文件的加载和施行并行进行(异步),不有限支撑顺序
defer:加载渲染后续文书档案成分的历程和.js文件的加载和履行并行举办(异步),但.js文件进行须求在享有因素解析完之后,DOMContentLoaded事件触发此前到位。

白屏时间和补救措施

在 Wi-Fi 下,那 60
多帧的历程一眨眼就过去了,但在弱互连网下,如那里最极致的网络 GP奥迪Q5S
下,整个首屏含图片全部加载成功供给 41.25s。当然那 40
多秒进度能尽早出现内容,并渐进和谐地球表面现出来是相比较好的。

男装频道是修改过后的,比较在此之前的未处理的猜你欣赏页面,出现长日子的白屏,如下:

皇家赌场手机版 15

以下为本土生活修复后的成效:

皇家赌场手机版 16

白屏处理只要稍微注意下就能够,修复的惠及也大约,尽量同步输出,异步输出请尽量
mock 出现在首屏的模板。假使是遵照 Cake\[3\]
工具开发的,也得以直接用首屏填充伪标签。

页面可知时间

页面可知要经历以下进程:

  • 解析 HTML 为 DOM,解析 CSS 为 CSSOM(CSS Object Model)
  • 将 DOM 和 CSSOM 合成一棵渲染树(render
    tree皇家赌场手机版,)
  • 达成渲染树的布局(layout)
  • 将渲染树绘制到显示器

皇家赌场手机版 17

layout

皇家赌场手机版 18

由于 JS 大概随时会变动 DOMCSSOM,当页面中有大气的 JS
想及时实施时,浏览器下载并施行,直到实现 CSSOM
下载与营造,而在我们拭目以俟时,DOM 构建同样被卡住。为了 JS 不阻塞 DOM 和
CSSDOM 的创设,不影响首屏可知的小时,测试三种 JS
加载策略对页面可知的震慑:

网页渲染机制
  • 解析HTML标签,构建DOM树
  • 解析CSS标签,构建CSSOM树
  • 把DOM和CSSOM合成Render树
  • 内测测算数据并将页面Layout
  • 绘制页面Painting

实际流程:
浏览器通过url得到html文件后会从上到下加载并实行分析和渲染。当碰着外部css文件或图表则发送请求此进度还要展开(异步)。因为js文件有大概要修改DOM所以HTML的加载渲染会在js文件分析完结后,因而当境遇js文件时HTML会挂起渲染的线程等js记载完结后接二连三html的加载渲染(白屏原因)。HTML的渲染进度是将代码依据深度优先遍历生成DOM
tree,CSS加载渲染完后生成CSSOM tree,DOM和CSSOM合成Render
tree,然后浏览器先导Layout最终Painting

皇家赌场手机版 19

结束语

上述在 Chrome 上的测试,但实质上在手淘里面,在
spdy、https、离线包内置能源等的熏陶下,它的瀑布流依然这么的啊?

二种异步加载情势测试

  • A. head script: 即普通的将 JS 放在 head 中或放在 body
    中间:DEMO 地址
  • B. bottom script: 即常规的优化策略,JS 放body的底部:DEMO
    地址
  • C. document.write: 在此以前 PC 优化少用的一种异步加载 JS 的国策:DEMO
    地址
JavaScript

function injectWrite(src){ document.write('&lt;script src="' + src +
'"&gt;&lt;/sc' + 'ript&gt;'); }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5a721bbc827ff070447677-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc827ff070447677-2">
2
</div>
<div class="crayon-num" data-line="crayon-5a721bbc827ff070447677-3">
3
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5a721bbc827ff070447677-1" class="crayon-line">
function injectWrite(src){
</div>
<div id="crayon-5a721bbc827ff070447677-2" class="crayon-line crayon-striped-line">
  document.write('&lt;script src=&quot;' + src + '&quot;&gt;&lt;/sc' + 'ript&gt;');
</div>
<div id="crayon-5a721bbc827ff070447677-3" class="crayon-line">
}
</div>
</div></td>
</tr>
</tbody>
</table>
  • D. getScript: 形如以下,也是 KISSY
    内部的getScript函数的简易完成:DEMO
    地址
JavaScript

&lt;script&gt; var script = document.createElement('script');
script.src = "//g.tbcdn.com/xx.js";
document.getElementsByTagName('head')\[0\].appendChild(script);
&lt;/script&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc82807359027480-2">
2
</div>
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc82807359027480-4">
4
</div>
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-5">
5
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5a721bbc82807359027480-1" class="crayon-line">
&lt;script&gt;
</div>
<div id="crayon-5a721bbc82807359027480-2" class="crayon-line crayon-striped-line">
  var script = document.createElement('script');
</div>
<div id="crayon-5a721bbc82807359027480-3" class="crayon-line">
  script.src = &quot;//g.tbcdn.com/xx.js&quot;;
</div>
<div id="crayon-5a721bbc82807359027480-4" class="crayon-line crayon-striped-line">
  document.getElementsByTagName('head')[0].appendChild(script);
</div>
<div id="crayon-5a721bbc82807359027480-5" class="crayon-line">
&lt;/script&gt;
</div>
</div></td>
</tr>
</tbody>
</table>
  • E. 加 async 属性:DEMO
    地址
  • F. 加 defer 属性:DEMO
    地址
  • G. 同时加 async defer 属性:DEMO
    地址

注:

  • [1]: TMS 为天猫内部运行活动系统。
  • [2]: TCE 为Taobao内部数据接口系统。
  • [3]: Cake 为天猫商城内部前端开发套件。

 

1 赞 收藏 1
评论

皇家赌场手机版 20

测试结果

以下提到的 domReadyDOMContentLoaded 事件。

A (head script) B (bottom script) C (document.write) D (getScript) E (async) F (defer) G (async + defer)
1 PC Chrome 页面白屏长、domReady:5902.545、onLoad:5931.48 页面先显示、domReady:5805.21、onLoad:5838.255 页面先显示、domReady:5917.95、onLoad:5949.30 页面先显示、domReady:244.41、onLoad:5857.645 页面先显示、domReady:567.01、onLoad:5709.33 页面先显示、domReady:5812.12、onLoad:5845.6 页面先显示、domReady:576.12、onLoad:5743.79
2 iOS Safari 页面白屏长、domReady:6130、onLoad:6268.41 页面白屏长、domReady:5175.80、onLoad:5182.75 页面白屏长、domReady:5617.645、onLoad:5622.115 502s 白屏然后页面显示最后变更 load finish 时间、domReady:502.71、onLoad:6032.95 508s 白屏然后页面显示最后变更 load finish time domReady:508.95、onLoad:5538.135 页面白屏长、domReady:5178.98、onLoad:5193.58 556s 白屏然后页面显示最后变更 load finish 时间、domReady:556、onLoad:5171.95
3 iOS 手淘 WebView 页面白屏长、页面出现 loading 消失、domReady: 5291.29、onLoad:5292.78 页面白屏长、页面未跳转 loading 消失、domReady: 5123.46、onLoad:5127.85 页面白屏长、页面未跳转 loading 消失、domReady: 5074.86、onLoad:5079.875 页面可见快、loading 消失快在 domReady 稍后、domReady:14.06、load finish:5141.735 页面可见快、loading 消失快在 domReady 稍后、domReady:13.89、load finish:5157.15 页面白屏长、loading 先消失再出现页面、domReady: 5132.395、onLoad:5137.52 页面可见快、然后 loading 消失、domReady:13.49、load finish:5124.08
4 Android browser 页面白屏长、domReady: 5097.29、onLoad:5100.37 页面白屏长、domReady: 5177.48、onLoad:5193.66 页面白屏长、domReady: 5125.96、onLoad:5165.06 页面可见快、等 5s 后更新 load finish 时间 domReady:463.33、load finish:5092.90 页面可见快、等 5s 后更新 load finish 时间 domReady:39.34、load finish:5136.55 页面白屏长、domReady: 5092.45、onLoad:5119.81 页面可见快、等 5s 后更新 load finish 时间 domReady:50.49、load finish:5507.668
5 Android 手淘 WebView 白屏时间长、一直 loading 直接页面可见、domReady:5058.91、onLoad:5073.81 页面立即可见、loading 消失快、等 5s 后更新 domReady 时间和 load 时间 domReady:4176.34、onLoad:4209.50 页面立即可见、loading 消失快、domReady:6011.18、onLoad:6031.93 页面可见快、loading 之后消失、等 5s 后更新 load finish 时间 domReady:36.31、load finish:5081.76 页面可见快、loading 随后消失、等 5s 后更新 load finish 时间 domReady:25.11、load finish:5113.81 页面可见快、loading 随后消失、等 5s 后更新 domReady 时间和 load 时间 domReady:5213.11、load finish:5312.19 页面可见快、loading 随后消失、等 5s 后更新 load finish 时间 domReady:89.67、load finish:5589.95

从上述测试结果能够见到以下结论:

  • 横向看, iOS Safari 和 Android browser
    的在页面可知、domReady、onLoad 的小运表现同样。
  • 纵向看,bottom script、document.write 和 defer 三列,可见document.write 和 defer 无别的异步效果,可知时间、domReady、onLoad
    的触发时间和 bottom script 的动静一样。
  • 纵向看,async + defer 联合用和 async 的显示同样,故合并为 async。
  • 纵向看,script 放页头(head script)和 script 放 body 底部(bottom
    script)。iOS Safari 、Android browser 和 iOS WebView 表现同样,就算script 放在 body 的最底层也不算,页面白屏时间长,要等到 domReady
    5s 多后停止才展现页面;唯独 Android WebView 的显现和 PC 的 Chrome
    一致。
  • 单纯看手淘 WebView 容器中 loading 消失的时辰,这几个时间点 iOS 和
    Android 的显示一致,即都以在 UIWebView 的 didFinishLoad
    事件触发时消失。那么些事件的接触可能在 domReady
    此前(如:A三 、B3),也大概在 domReady
    之后(如:D③ 、E3);那些事件触发和 JS 中的 onLoad
    触发时机也不曾必然的关联,或然在 onLoad 在此以前(如:D叁 、E3)也说不定在
    onLoad 差不离与此同时(如:A5)。 didiFinishLoad
    到底是如曾几何时机触发的吗,详见下章。
  • 页面可见时间,getScript 格局和 async 格局页面可知都丰硕快,domReady
    的时日接触得也不行快,客户端的 loading 在 domReady
    稍后即没有。原因是因为末段耗时的 JS
    请求异步化了,没有阻塞浏览器的
    DOM + CSSOM 塑造,页面渲染完结就立马可(马克)见了。全体看,假使 domReady
    的日子快,则页面可知快;反之即使页面可知快,domReady
    的光阴不自然快,如 B五 、B一 、C壹 、C伍 、F① 、F5。如若异步化耗时间长度的
    JS,domReady 和 onLoad 的年华差别是一点都不小的,不做其余处理 onLoad
    的年月 domReady 的年月差 30ms 左右。所以在异步化的前提下,能够用
    domReady 的岁月作为页面可知的小时。

didFinishLoad 到底什么日期接触

didFinishLoad 是 native 定义的轩然大波,该事件触发时手淘 loading
秋菊消失,并且 windvane 中的发出请求不再收集,也便是 native 总结出的
pageLoad 时间。在用户数量平台来看的瀑布流请求,正是在 didFinishLoad
触发前收集到的拥有请求。

皇家赌场手机版 21

通过上方测试,客户端的 didFinisheLoad 事件的触及和 JS 中的
domReady(DOMContentLoaded)和 onLoad 触发没有其它关系。或许在 domReady
以前或今后,也可能在 onLoad 此前或之后。

那它到底是如什么日期候接触呢? iOS
官方文书档案
是 Sent after a web view finishes loading a frame。
结合收集的用户请求和测试,didFinishLoad
是在三番五次发起的伸手截至以往触发,监听一段时间内无请求则触发。

于是不时会看出 data_sufei 这一个 JS
文件,在有个别用户的瀑布流里面有,在多少用户的又不曾。原因是那么些 JS 是
aplus_wap.js 故意 setTimeout 1s 后发生的,如若页面在 1s
前持有的央求都发完了则触发 didFinishLoad,前面包车型大巴 data_sufei.js
的岁月就不算到 pageLoad 的岁月;反之假诺类似 1s
页面还有图片等请求还在发,则 data_sufei.js 的时日也会被算到里面。

从而在 JS 中用 setTimeout 来推迟发送请求也有大概会影响 didFinishLoad
的年华,提议 setTimeout 的小运设置得更长一些,如 3s。

async 和 defer

script 标签上能够添加 defer 和 async 属性来优化此 script 的下载和实行。

defer :延迟

HTML 4.0 规范,其功用是,告诉浏览器,等到 DOM+CSSOM
渲染完结,再履行内定脚本。

JavaScript

<script defer src=”xx.js”></script>

1
<script defer src="xx.js"></script>
  • 浏览器初叶解析 HTML 网页
  • 剖析进度中,发现带有 defer 属性的 script 标签
  • 浏览器继续往下分析 HTML 网页,解析完就渲染到页面上,同时并行下载
    script 标签中的外部脚本
  • 浏览器完结解析 HTML 网页,此时再实施下载的脚本,达成后触发
    DOMContentLoaded

下载的脚本文件在 DOMContentLoaded
事件触发前实施(即刚刚读取完标签),而且能够保障执行各种就是它们在页面上出现的次第。所以
添加 defer 属性后,domReady
的日子并不曾提前,但它能够让页面更快呈现出来。

将位于页面顶端的 script 加 defer,在 PC Chrome 下其作用相当于 把那些script 放在底部,页面会先出示。 但对 iOS Safari 和 iOS WebView 加 defer
和 script 放尾部一样都以长日子白屏。

async: 异步

HTML 5
规范,其意义是,使用另二个历程下载脚本,下载时不会阻塞渲染,并且下载完结后立即实施。

JavaScript

<script async src=”yy.js”></script>

1
<script async src="yy.js"></script>
  • 浏览器伊始解析 HTML 网页
  • 剖析进度中,发现带有 async 属性的 script 标签
  • 浏览器继续往下分析 HTML 网页,解析完先呈现页面并触发
    DOMContentLoaded,同时并行下载 script 标签中的外部脚本
  • 本子下载实现,浏览器暂停解析 HTML 网页,开始施行下载的脚本
  • 剧本执行完成,浏览器复苏解析 HTML 网页

async 属性可以保障脚本下载的同时,浏览器继续渲染。不过 async
无法保障脚本的施行顺序。哪个脚本先下载截止,就先举行那些剧本。

怎么选择 async 和 defer

  • defer 能够确定保障实施各类,async 不行【注:hack】
  • async 能够提前触发 domReadydefer 不行【注:Firefox 的
    defer 也能够提前触发 domready
  • defer 在 iOS 和一些 Android 下如故阻塞渲染,白屏时间长。
  • 当 script 同时加 asyncdefer
    属性时,后者不起功能,浏览器行为由 async 属性决定。
  • asyncdefer 的包容性不均等,幸亏 asyncdefer
    有线端基本都协助,async 不支持 IE 9-。
    附 async 兼容性 defer
    兼容性

script inject 和 async

JavaScript

<!– BAD –> <script
src=”//g.alicdn.com/large.js”></script> <!– GOOD –>
<script> var script = document.createElement(‘script’); script.src
= “//g.alicdn.com/large.js”;
document.getElementsByTagName(‘head’)[0].appendChild(script);
</script>

1
2
3
4
5
6
7
8
9
  <!– BAD –>
<script src="//g.alicdn.com/large.js"></script>
 
<!– GOOD –>
<script>
  var script = document.createElement(‘script’);
  script.src = "//g.alicdn.com/large.js";
  document.getElementsByTagName(‘head’)[0].appendChild(script);
</script>

咱俩见惯司空用那种 inject script 的章程来异步加载文件,尤其是原先
Sea.jsKISSY 的风靡时,出现多量利用$.use
来加载页面入口文件。那种办法和 async 的一律都能异步化
JS,不打断页面渲染。但着实是最快的呢?

三个科普的页面如下:叁个 CSS,三个异步的 JS

JS 使用 script inject
的不二法门测试结果如下,DEMO:

皇家赌场手机版 22

JS 使用 async 的法子测试结果如下,
DEMO:

皇家赌场手机版 23

比较结果发现,通过 “ 的措施的 JS 能够和 CSS 并发下载,那样一切页面 load
时间变得更短,JS
更快执行完,那样页面包车型客车互动或数量等得以更快更新。为啥吧?因为浏览器有类似
‘preload
scanner’
的效应,在 HTML 解析时就能够提前并发去下载 JS 文件,要是把 JS
的文书隐藏在 JS 逻辑中,浏览器就没那样智能发现了。

或许大家会说,未来 CSS/JS
都预加载到客户端了,怎么加载不根本。但页面有恐怕分享出来也有恐怕运维在浏览器中,也有恐怕预加载失效。

总结上边 async 和 defer,推荐以下用法。

JavaScript

<!– 现代浏览器用 ‘async’, ie9-用 ‘defer’ –> <script
src=”//g.alicdn.com/alilog/mlog/aplus_wap.js” async
defer></script>

1
2
<!– 现代浏览器用 ‘async’, ie9-用 ‘defer’ –>
<script src="//g.alicdn.com/alilog/mlog/aplus_wap.js" async defer></script>

实质上今后有线站点 aplus.js 能够完全用那种办法引入,既不会卡住 DOM
CSSOM,也不会延伸整个页面 onLoad 时间,而不是原先的 PC 上的
script inject方式。

假诺 aplus.js 在 PC 上这么用,IE 8/IE 9 应用的是 defer
属性,不会卡住页面渲染,可是这些 JS 供给执行完后才触发
domReady(DOMContentLoaded)事件,故在 IE 8/IE 9 下或许会潜移默化 domReady
的日子。

末了提出

  • 事务 JS 尽量异步,放 body 底部的 JS 在 iOS 上和一些 Android
    是无用的,依旧会卡住首屏渲染。
  • 异步的方法尽或许原生用async,容器(浏览器、webview
    等)级别自带优化,不要通过 JS 去模拟完结,如
    getScript/ajax/KISSY.use/$.use 等。
  • 有各种信赖关系的 JS 能够加
    defer,不改动执行顺序,相当于放到页面底部,如 TMS head
    中暂且不能活动地点的类库等。

参考资料

  • 1 赞 2 收藏
    评论

Leave a Comment.