@ledsun blog

無味の味は佳境に入らざればすなわち知れず

HTMLのscriptタグのdefer属性

HTMLのscriptタグにdefer属性があります。 これを使うと何が嬉しいのでしょうか?

スクリプトがDOM構築に与える影響

スクリプトdocument.write を実行してHTMLを操作することが許されています。 このため、ブラウザは<script>タグを見つけると、DOM構築を一度停止し

  1. スクリプトをダウンロード
  2. スクリプトを実行

します。それからDOM構築を再開します。<script>タグの存在は、DOM構築の時間を長くします。これはホームページの初期表示し掛かる時間が長くなることを意味します。

スクリプトダウンロード時間の影響を小さくする方法

スクリプトをダウンロードする時間を回避するためには「ハイパフォーマンスWebサイト」の「ルール6:スクリプトは最後に置く」で、<body>タグの末尾に<script>タグを書く方法が紹介されています。

例えば、次のように書きます。

<html>
  <body>
    <script src="script.js"></script>
  </body>
</html>

スクリプト実行時間の影響を小さくする方法

また、スクリプト実行時間の影響を小さくするための方法として、スクリプト内で時間の掛かる処理を、setTimeoutまたはDOMContentLoadedイベントのイベントハンドラーとして設定し、DOM構築のあとに実行する方法があります。

例えば、次のように書きます。

<html>
  <head>
    <script>
    document.addEventListener('DOMContentLoaded', () => {
      // スクリプトのメイン処理
    })
    </script>
  </head>
</html>

スクリプト実行した時はイベントハンドラーの設定だけし、メイン処理はイベント発火時に実行します。

defer属性

この2つの方法を属性ひとつで実現するのがdeferです。

defer属性のついたスクリプトは、document.writeの使用が禁止されます。これにより、ブラウザはスクリプトがHTMLを変更する可能性を気にしなくてよくなります。 defer属性のついたスクリプトを、DOM構築の最後、DOMContentLoadedイベントの前に実行できます。

例えば次のように書きます。

<html>
  <head>
    <script defer src="script.js"></script>
  </head>
</html>

インラインスクリプトでは効果が無いようです。

script要素のdefer属性でパフォーマンスを向上 によると2013年頃はまだサポートしていないブラウザがあったようです。

デスクトップ主要ブラウザの中ではOperaのみがサポートしていないブラウザとして残ったのですが、2013年7月にOpera 15.0としてリリースされた、OperaからはChromiumレンダリングエンジンとしてBlinkを搭載したものになっており、defer属性をサポートしています。

現在では、サポートしていないブラウザはなさそうに思います。 とりあえずdeferに慣れる意味で、つぎの運用をしています。

  1. <head>タグに<script>タグを書く
  2. DOM構築の後に実行したくななったら、defer属性をつける

参考