script非同期読み込みのススメ

26_asyncdefer.jpg

freoのデフォルトテンプレートでは外部javascriptを読み込むためのタグ、「<script src=~略」が<head>~</head>に記述されています。実はこの記述順序は、ページの表示を遅らせる一因となってしまいます。

なぜ<head>~</head>でscriptタグを記述するとページの表示が遅くなる?

ブラウザは上から順番にHTMLを読み込み解析作業をし、表示していくのですが、その途中で外部ファイルを読み込む記述があるとその外部ファイルをダウンロードし実行するまでHTMLの読み込みが中断されるためです。(画像は参考元の「<script> タグに async / defer を付けた場合のタイミング - Qiita」さんから流用させていただいています)

対処法その1:scriptタグを後ろのほうに移動する

<head>~</head>内の「<script src=~略」の記述をごっそりそのまま</body>の直前に持っていきます。こうすることでHTMLレンダリングが終わってから外部スクリプトの読み込みが開始されます。

freoのテンプレートであれば、templates/header.htmlからtemplates/footer.htmlへ記述の移動をします。この時複数あるscriptタグの順序は変更しないよう注意。

対処法その2:asyncまたはdefer属性を使う

HTML5ではscriptタグにasyncまたはdefer属性を付与することで外部スクリプトを非同期に読み込むことができます。

async属性の記述法

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

defer属性の記述法

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

async属性とdefer属性の違い

asyncdeferも、スクリプトのダウンロード時にHTMLの解析を阻害しません。

  • async→スクリプトのダウンロードが完了した時点でスクリプトを実行
  • defer→スクリプトのダウンロードが完了してもHTML解析が終了するまでスクリプト実行を待機
  • async→スクリプトの実行順序は不定(ダウンロードが先に終わったものから実行される)
  • defer→HTMLの記述順通りに実行される

という違いがあります。特に実行順序に気を付けなければならないのはスクリプト同士が依存関係にある場合です(jQueryとjQueryプラグイン等)。この場合はdefer属性を付与するほうが吉。

おまけ:CSSの非同期読み込みは?

HTML5.2以降では<link rel="stylesheet"><style type="text/css">~</style>をbody内に記述できるようになっています。

しかし、これは従うべき良い方法ではありません。 <link> 要素は <head> に入れて本文から離した方が分かりやすくなります。

また、一度レンダリングしたHTMLに後から読み込んだスタイルを適用することになるため逆効果なのではという意見もあります。

参考までに、「CSSを非同期ロードする最も簡単な方法 - Qiita」のような方法もあります。