script要素のdefer属性の実装

<!--HTMLでは--><script defer></script>
<!--XHTMLでは--><script defer="defer"></script>

script要素にはdefer属性があって、これはdocument.write系がないことを条件にscriptの中身を後で評価することによってページのレンダリングを妨げないようにするものと説明されている。ただdeferが利用されているサイトってなかなか見たこと無いうえに本当にレンダリングを妨げないか興味があったので調べた。

実装されているブラウザ

調べた範囲ではIE(SafariとKon〜は調べてない)のみ。あとIEはscript要素にdefer属性をつけるとinnerHTMLに代入したscriptが実行されるという仕様がある。

// 以下は動かないので駄目
hoge.innerHTML = "hoge<script>alert('hoge')</script>";
// ちゃんとallertされます
hoge.innerHTML = "hoge<script defer>alert('hoge')</script>";

確かにレンダリングを妨げない

  • IEでは確かにHTMLのHello World!!が出た後に数秒後(ここでは2秒)にalert("Hello World!!");
  • fxなどでは2秒間待たされた後にalert("Hello World!!");してその直後にHello World!!が描画されている。

http://labs.starmsg.net/samples/07030601.php

検証方法とか

実装を調べるにあたって読込むスクリプトを重くしないといけないが重いサーバの演出が難しいし回線も細くないので以下みたいにPHPでsleepをかけて見て検証した。

<?php
sleep(2); // 2秒待
header('text/javascript');
?>
alert('Hello World!!');

評価の順番

<script defer src="foo.js"></script>
<script defer>alert("script2");</script>
<script src="bar.js"></script>
<script defer src="hoge.js"></script>

例えば上記の例では【alert("script2")】された後に【bar.js】が実行されて【foo.js】→【hoge.js】というふうに実行された。というわけでdeferはsrc属性で外部スクリプトを呼び出すときに有効か?window.onloadのタイミングはdeferが指定された外部スクリプトを評価し終わったときに発生した。defer属性指定されたscript要素は出てきた順番に評価された(foo.js→hoge.js)

JavaScriptからdefer要素の設定

MSDNW3CのDOM勧告を見る限りではdeferの型はBooleanの為にJavaScriptからdefer要素設定する場合には以下のように設定すべきみたい(IEのときのみ)。デフォルトはfalse。

script = document.createElement('script');
script.setAttribute('defer', true);
// あるいは
// script.defer = false;

IE以外では以下のようにする。

script.setAttribute('defer', 'defer');

でも

いまいち利用どころが分からない。

追記した

  • 2007/03/07 nanto_viさんからのコメントいただき加筆訂正す。