defer/asyncチェックツールを作りブラウザ対応状況を確認してみた

browsers

ちょっと前に 「scriptのdefer/asyncを理解し、ページの高速化方法を探る」 というエントリーを書きましたが、はてなのブックマーカー edvakf さんから 「Opera は defer も async も対応してないはず」 というご指摘を頂きました (edvakf さん、ありがとうございます)。

こちらこちら (2012年11月16日:Google のドキュメントが削除されました) の表を 「対応状況」 としてそのまま流用してしまったのが失敗でした。英語をよく読めば、You can use the defer/async attribute on the following elements と書いてあります。つまり 属性は使えるけど、動作は別 とも読めるわけで…。

ということで、「defer/async チェッカー (仮)」 を作ってリベンジすることにしました。

1.defer/asyncチェッカー(仮)

一応 Cuzillion をヒントに作っていますが、「チェッカー」 といっても自動チェック機能はなく、目視でチェックするヘボなツールです。その特徴は次の通りです。

チェッカーの概要

チェッカーの概要

  • ドキュメントタイプの切り替えと deferasync 属性の On / Off
  • スクリプト実行 (DOM への文字挿入) 状況を確認する機能
  • JavaScript ファイルの読み込みに時間差を付ける機能
  • イベントの発生順序、およびオブジェクト状態の変化順序を確認する機能
  • document.write() 利用時の影響を確認する機能

チェックを開始する

1.1動作原理

以下の様に、メインコンテンツ部分 「Hello」 と 「World!」 のパラグラフ間に3つのスクリプトを挟み、各スクリプトはそれぞれ 「A」、「B」、「C」 というパラグラフを生成します。それぞれは2秒、1秒、0秒の待ち時間の後にスクリプトを送出しますので、DOM の構築がブロックされる様子を確認することが出来ます。即ち deferasync が有効であれば、いち早く 「Hello Wold!」 のコンテンツが完成するわけです :-D

HTMLの主要部分
<div id="main">
	<p>Hello</p>
	<script type="text/javascript" id="A" src="script.php?id=A&wait=2000" defer></script>
	<script type="text/javascript" id="B" src="script.php?id=B&wait=1000" defer></script>
	<script type="text/javascript" id="C" src="script.php?id=C&wait=0" defer></script>
	<p>World!</p>
</div> <!-- main -->

属性の指定方法は、HTML 4.01 と HTML5 では単に defer、XHTML1.0/1.1 では defer="defer" となります。ドキュメントタイプと属性の指定方法については 「scriptのdefer/asyncを理解し、ページの高速化方法を探る」 にまとめてありますので、そちらを参照ください。

JavaScript (A、B、C の3種類)
var e = document.createElement('p');
e.innerHTML = 'A'; // 'B', 'C'
document.getElementById('main').appendChild(e);
JavaScript を生成する script.php

上記3つのスクリプトファイル生成時に、引数として wait=2000 (2秒スリープ後にスクリプトを送信) に様に、時間差を付ける機能を実装しました。

1.2確認方法

属性無し あるいは 非対応

属性無し or 非対応

右図の様に、スクリプトのローディングにより 「Hello」 以降の DOM 構築がブロックされます。「A」、「B」、「C」は同時にローディングされていますが、その評価・実行順序は保持されるので、2秒後、ほぼ同時かつ A → B → C の順に DOM が挿入され、「World!」 でページの表示が完成します。

deferが有効

deferが有効

「Hello World!」 までの DOM 構築が先に行われます。一方、スクリプトはローディングはされていますが、その評価・実行は DOM 構築完了まで遅延されます。かつその順序は同期的に保存されます。

asyncが有効

asyncが有効

「Hello」 の DOM 構築後、各スクリプトのローディングが非同期に開始されます。またローディングが終了した順に非同期に評価・実行が行われるため、C → B → A の順に表示されることになります。仮に 「World!」 が画像で、そのローディングにも時間がかかる様な場合には、「C」 の方が先に表示されることもあり得ます (事実、キャッシュからのローディングの場合には、そうなる可能性が高い)。

1.3イベント or 状態のログについて

オマケで、オブジェクトからのイベント (DOMContentLoadedonload) や状態 (readyState) の変化をキャプチャしてログする機能を付けてみました。Firebug のを開いていれば、コンソールにリアルタイムにログを出力しています。

readyState Property – MSDN LibraryreadyState の定義がありますので、掲載しておきます。

名称 状態
uninitialized オブジェクトはまだ初期化されていない
loading オブジェクトはデータをローディング中である
loaded オブジェクトはデータのローディングを完了した
interactive 完全にロードされたわけではないが、ユーザはオブジェクト関わることができる
complete オブジェクトは完全に初期化された

interactive の意味は、「プログラムは実行可能だよ」 とか 「DOM の一部はアクセス可能だよ」 とかだと思います。

また、例として Firefox と IE8 のログを載せておきます。特に IE は、script 要素にも readyState があるのが分かります。ブラウザの中身がちょっと覗けたような感じがして、ちょっぴりウレシイです。

Firefox3.6のログ

Firefox3.6のログ

IE8のログ

IE8のログ

参考情報

2.主要ブラウザの対応状況

さて、ヘボなチェッカーで手持ちのブラウザを確かめてみました。

ブラウザ HTML 4.01 XHTML 1.0/1.1 HTML5
defer defer defer async
IE6 Y Y Y N
IE7 Y Y Y N
IE8 Y Y Y N
Safari4 N N N N
Safari5 N N N N
Opera10 N N N N
Chrome7 Y Y Y N
Chrome8 Y Y Y Y
Firefox3.6 Y Y Y Y

IE は HTML5 に対応しているというより、属性の指定方法が HTML 4.01 と同じため、機能しているということだと思います。またいつの間にか Chrome が 7 から 8 にアップしていて、async に対応していました。Safari などは、defer 属性値を持っており、true をセットすれば、それが保持されるようです。だからといって非同期読み込み・実行がされるわけではないのですネ。

参考情報

defer/asyncチェックツールを作りブラウザ対応状況を確認してみた」への1件のフィードバック

  1. ピンバック: Tweets that mention ゆっくりと… » defer/asyncチェックツールを作りブラウザ対応状況を確認してみた -- Topsy.com

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

海外からの投稿は受け付けていません