ブログ
scriptの非同期読み込み
どうも、エンジニアの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>
タグのasync
とdefer
属性を使うと、非同期での読み込みとscriptの実行タイミングを指定できます。
何も指定せずscriptタグを入れる場合HTMLのパース処理が上から行われ、<script>
タグの部分でJSのダウンロード、パースに移行し処理が終わったところで、HTMLのパース処理に戻ってきます。
<script src="/js/script.js"></script>
ここで<script>
タグにasync
かdefer
属性を指定すると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実行タイミング
当然ですが、async
やdefer
を指定するとJSの実行タイミングが変わってきます。
外部ファイルに依存しているJSはasync
で指定してしまうと、ダウンロード完了のタイミングによっては依存先のJSファイルの読み込みが完了していない場合もあるので注意しましょう。
イベント実行タイミング
また、ダウンロード完了のタイミングによってはDOMContentLoaded
イベントがトリガーされた後に実行される可能性があるので、loadの完了を待って処理をする場合は気をつける必要があります。
jQueryの場合はdocument.readyState
を見ているようなのでそのままでも問題なさそうです。
まとめ
いかがでしたでしょうか
私自身、async
、defer
属性はなんとなく知っていましたが細かい動作を把握していない部分もあり、積極的に使ってはいませんでした。
これからはしっかり使い分けて活用していけそうです。
それではまた。