ホームページ >ウェブフロントエンド >htmlチュートリアル >ワイヤレス パフォーマンスの最適化: ページの表示時間と非同期読み込み_html/css_WEB-ITnose

ワイヤレス パフォーマンスの最適化: ページの表示時間と非同期読み込み_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:28:591625ブラウズ

特にワイヤレス環境において、ページをできるだけ早くレンダリングし、ページをより早く表示し、白い画面時間を短縮する方法は、常にパフォーマンス最適化のトピックです。

ページの表示時間

ページは次のプロセスを経て表示されます:

  • HTMLをDOMに解析し、CSSをCSSOM (CSS Object Model)に解析します
  • DOMとCSSOMをレンダーツリーに結合します(レンダーツリー)
  • レンダリングツリーのレイアウト(レイアウト)を完了する
  • レンダリングツリーを画面に描画する

layout

JSはいつでもDOMやCSSOMを変更する可能性があるため、ページ内に大量のJSがある場合、すぐに実行したい場合、ブラウザーは CSSOM のダウンロードとビルドが完了するまでダウンロードして実行します。待機している間、DOM ビルドもブロックされます。 JS が DOM と CSSDOM の構築をブロックしないように、また最初の画面の表示時間に影響を与えないように、いくつかの JS 読み込み戦略がページの表示に与える影響をテストします。

いくつかの非同期読み込みメソッドをテストする

  • A. head スクリプト: つまり、通常の JS が head または body の途中に配置されます: DEMO アドレス
  • B.bottom スクリプト: 従来の最適化戦略であり、JS が body の最後に配置されます: DEMO アドレス
  • C. document.write: 過去に PC の最適化にほとんど使用されなかったスクリプト JS を非同期でロードする戦略: DEMO アドレス

    function injectWrite(src){  document.write('<script src="' + src + '"></sc' + 'ript>');}

  • D. getScript: フォームは次のとおりです。 KISSY の内部 getScript 関数の簡単な実装: DEMO アドレス

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

  • E. 非同期属性を追加: DEMO アドレス

  • F. defer 属性を追加: DEMO アドレス
  • G. async defer 属性も追加: DEMO アドレス

テスト結果

以下で説明する domReady は DOMContentLoaded イベントと同じです。

1最初にページが表示されます, domReady:5917.95、onLoad:5949.30最初にページが表示されます, domReady:244.41, onLoad:5857.645最初にページが表示されます, domReady:567.01, onLoad:5709.33最初にページが表示されます, domReady:58 12.12、 onLoad:5845.6 最初にページが表示されます、 domReady:576.12 、 onLoad:5743.792iOS Safari ページの白い画面の長さ、 domReady:6130 、 onLoad:6268.41ページの白い画面の長さ、domReady: 5175.80、onLoad:5182.75ページの白い画面の長さ、domReady: 5617.645、onLoad:5622.115502s の白い画面、その後ページに最後の変更のロード終了時間、domReady:502.71、onLoad:6032.95508s が表示されます画面に続いてページには最後の変更のロード終了時間が表示されます domReady:508.95、onLoad:5538.135ページが白 画面の長さ、ドメイン: 5178.98、のみ: 5193.58 556 秒の白い画面、その後ページ表示 ロード終了時間、domream: 556、のみ: 5171.95Android ブラウザ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5: 5058.91、のみ: 5073.81 ページがページに表示され、読み込みがすぐに消えます。5 秒待ってから domReady を更新します時間とロード時間 domReady:4176.34、onLoad:4209.50ページはすぐに表示され、ロードはすぐに消えます、domReady:6011.18、onLoad:6031.93ページはすぐに表示され、ロード後に消えます、5秒待ってからロード終了時間を更新しますdomReady: 36.31、読み込み終了: 5081.76ページがすぐに表示され、読み込み後に消える、5秒待ってから読み込み終了時間を更新する domReady: 25.11、読み込み終了: 5113.81ページがすぐに表示され、読み込み後に消える、待つ5秒 次に、domReady時間とロード時間を更新します domReady: 5213.11、ロード終了: 5312.19 ページがすぐに表示され、ロードしてから消えます。5秒待ってからロード終了時間を更新します domReady: 89.67、ロード終了: 5589.95
A (ヘッドスクリプト) B (ボトムスクリプト) D (getScript) E (非同期) F (遅延) G (a同期する+ defer)
PC Chrome ページは白くて長い、domReady:5902.545、onLoad:5931.48 最初にページが表示されます、domReady:5805.21、onLoad:5838.255
ios hand Amoy webview
画面が長く、ページが長く、ページ 読み込みが消えます、domReady: 5291.29、onLoad: 5292.78 ページの白い画面が長く、ページがジャンプせず、読み込みが消えます、domReady: 5123.46, onLoad: 5127.85 ページの白い画面が長い、ページが飛ばない、読み込みが消える、domReady: 5074.86、onLoad:5079.875 後でdomReadyでページがすぐに見える、読み込みがすぐに消える、domReady:14.06、ロード終了:5141.735 ページはすぐに表示され、ロードは後でdomReadyですぐに消えます、domReady:13.89、ロード終了:5157.15 ページ ページは白くて画面が長く、ロードが最初に消えてから表示されます、domReady: 5132.395 、onLoad:5137.52 ページはすぐに表示され、その後読み込みが消えます、domReady:13.49、読み込み終了:5124.08 4
ページは白くなります、domReady: 5097.29、onLoad: 5100.3 7 ページはすぐに表示され、ロード終了時間 domReady:463.33、ロード終了:5092.90 の後にページが更新されるまで 5 秒待ちます ページがすぐに表示され、5 秒待ってから更新ロード終了時間 domReady:39.34、ロード終了: 5136.55 ページの白い画面が長いです、domReady: 5092.45、onLoad:5119.81 ページはすぐに表示されます、お待ちください更新読み込み終了時間domream: 50.49、読み込み終了: 5507.668 Android hand Tao WEBVIEW

从以上测试结果可以看出以下结论:

  • 横向看, 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 之前(如:A3、B3),也可能在 domReady 之后(如:D3、E3);这个事件触发和 JS 中的 onLoad 触发时机也没有必然的联系,可能在 onLoad 之前(如:D3、E3)也可能在 onLoad 几乎同时(如:A5)。 didiFinishLoad 到底是什么时机触发的呢,详见下章。
  • 页面可见时间,getScript 方式和 async 方式页面可见都非常快,domReady 的时间触发得也非常快,客户端的 loading 在 domReady 稍后即消失。原因是因为 最后耗时的 JS 请求异步化了 ,没有阻塞浏览器的 DOM + CSSOM 构建,页面渲染完成就立刻可见了。整体看,如果 domReady 的时间快,则页面可见快;反之如果页面可见快,domReady 的时间不一定快,如 B5、B1、C1、C5、F1、F5。如果异步化耗时长的 JS,domReady 和 onLoad 的时间差距是很大的,不做任何处理 onLoad 的时间 domReady 的时间差 30ms 左右。所以在异步化的前提下,可以用 domReady 的时间作为页面可见的时间。

didFinishLoad 到底什么时候触发

didFinishLoad 是 native 定义的事件,该事件触发时手淘 loading 菊花消失,并且 windvane 中的发出请求不再收集,也就是 native 统计出的 pageLoad 时间。在用户数据平台看到的瀑布流请求,就是在 didFinishLoad 触发前收集到的所有请求。

经过上方测试,客户端的 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 渲染完成,再执行指定脚本。

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

  • 浏览器开始解析 HTML 网页
  • 解析过程中,发现带有 defer 属性的 script 标签
  • 浏览器继续往下解析 HTML 网页,解析完就渲染到页面上,同时并行下载 script 标签中的外部脚本
  • 浏览器完成解析 HTML 网页,此时再执行下载的脚本,完成后触发 DOMContentLoaded

下载的脚本文件在 DOMContentLoaded 事件触发前执行(即刚刚读取完\ffcfa9cf6eaa5476ca5cdb4e90c503a8标签),而且可以保证执行顺序就是它们在页面上出现的顺序。所以 添加 defer 属性后,domReady 的时间并没有提前,但它可以让页面更快显示出来。

将放在页面上方的 script 加 defer,在 PC Chrome 下其效果相当于 把这个 script 放在底部,页面会先显示。 但对 iOS Safari 和 iOS WebView 加 defer 和 script 放底部一样都是长时间白屏。

async: 异步

HTML 5 规范,其作用是,使用另一个进程下载脚本,下载时不会阻塞渲染,并且下载完成后立刻执行。

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

  • 浏览器开始解析 HTML 网页
  • 解析过程中,发现带有 async 属性的 script 标签
  • 浏览器继续往下解析 HTML 网页,解析完先显示页面并触发 DOMContentLoaded,同时并行下载 script 标签中的外部脚本
  • 脚本下载完成,浏览器暂停解析 HTML 网页,开始执行下载的脚本
  • 脚本执行完毕,浏览器恢复解析 HTML 网页

async 属性可以保证脚本下载的同时,浏览器继续渲染。但是 async 无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本。

如何选择 async 和 defer

  • defer 可以保证执行顺序, async 不行【注:6b7320ad0c28679bff8cd62176e5c5a4 的方式的 JS 可以和 CSS 并发下载,这样整个页面 load 时间变得更短,JS 更快执行完,这样页面的交互或数据等可以更快更新。为什么呢?因为浏览器有类似 ‘ preload scanner ’ 的功能,在 HTML 解析时就可以提前并发去下载 JS 文件,如果把 JS 的文件隐藏在 JS 逻辑中,浏览器就没这么智能发现了。

    也许大家会说,现在 CSS/JS 都预加载到客户端了,怎么加载不重要。但页面有可能分享出去也有可能运行在浏览器中,也有可能预加载失效。

    综合上面 async 和 defer,推荐以下用法。

    <!-- 现代浏览器用 '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 的时间。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。