scriptの非同期読み込み

Blog

どうも、エンジニアのiwabuchiです。

今回は、個人的に調べようと思いつつも先延ばしになっていたscriptの非同期読み込みについて調べてみたので、まとめてみました。

scriptの非同期読み込み

近年はJavaScriptでできることの増加に伴いファイル容量も大きくなっており、
ブラウザのパース処理などをブロッキングしないで読み込むことが意識されることが多くなっています。

パース処理のブロッキングを短くするテクニックとして
下記のような感じでJavaScriptでscript要素を作りアペンドする手法があります。

<script>
   const script = document.createElement('script');
   script.src = "/js/script.js";
   document.getElementsByTagName('head')[0].appendChild(script);
</script>

上記のようにscript.jsを読み込む際にhtmlのパースなどをブロッキングせずに読み込むことができます。

最近はもっと簡単に<script>タグに属性をつけるだけで非同期の読み込みを実現できます。

asyncとdefer

<script>タグのasyncdefer属性を使うと、非同期での読み込みとscriptの実行タイミングを指定できます。

何も指定せずscriptタグを入れる場合HTMLのパース処理が上から行われ、<script>タグの部分でJSのダウンロード、パースに移行し処理が終わったところで、HTMLのパース処理に戻ってきます。

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

ここで<script>タグにasyncdefer属性を指定するとHTMLのパース処理を止めずにファイルを読み込むことができます。

async

asyncを指定すると非同期にファイルのダウンロード、実行が行われます。
<script>タグ部分でHTMLのパースを止めずに処理が進みます。
scriptの実行はファイルのダウンロードが完了したタイミングで実行されます。

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

defer

deferを指定するとファイルのダウンロードはasyncと同じく非同期で行われます。
こちらもHTML のパースを止めずにダウンロードが進みます。
scriptの実行はHTMLパース完了後に実行されます、かつ<script>タグが書かれている順番に実行されていきます。

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

注意点

script実行タイミング

当然ですが、asyncdeferを指定するとJSの実行タイミングが変わってきます。
外部ファイルに依存しているJSはasyncで指定してしまうと、ダウンロード完了のタイミングによっては依存先のJSファイルの読み込みが完了していない場合もあるので注意しましょう。

イベント実行タイミング

また、ダウンロード完了のタイミングによってはDOMContentLoadedイベントがトリガーされた後に実行される可能性があるので、loadの完了を待って処理をする場合は気をつける必要があります。

jQueryの場合はdocument.readyStateを見ているようなのでそのままでも問題なさそうです。

まとめ

いかがでしたでしょうか

私自身、asyncdefer属性はなんとなく知っていましたが細かい動作を把握していない部分もあり、積極的に使ってはいませんでした。
これからはしっかり使い分けて活用していけそうです。

それではまた。

参考サイト