JavaScript ファイルの読み込み方

この記事は最終更新日から 1年以上 が経過しています。

JavaScript ファイルを読み込むためには script タグを使用するわけですが、 その script タグの書き方をほんの少し変えるだけで処理速度は大きく変わってしまいます。 そこで、JavaScript ファイルの読み込み方をまとめておきます。 誰かのお役に立てば幸いです。

方法1:head タグの中で読み込む(デフォルト)

まずは、最も基本的な、script タグを head タグの中で読み込む方法です。 いわゆる普通の HTML の書き方ですね。 HTML を勉強したらまずはこの書き方を教わることでしょう。

ですが、この方法には1つ問題があります。 script タグが HTML パースをブロックしてしまい(パーサーブロッキング)、 JavaScript の読み込みと処理に時間がかかってしまって、画面の表示が少し遅れてしまうのです。

HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/example1.js"></script> // ①
<script src="/example2.js"></script> // ②
</head>
<body>

(省略:とっても長いHTML)// ③

</body>
</html>
pattern1.png

方法2:body タグの最下部で読み込む

方法1では、HTML パースをブロックしてしまい画面の表示が遅くなってしまうという問題がありました。 そこでその対策として、script タグを body タグの一番最後に記述するという方法が生まれました。 script タグが HTML パースをブロックしてしまうのであれば、 それを後回しにすれば良いじゃないかというアプローチですね。 body タグの一番最後に script タグが記述されていれば、 script タグが HTML パースをブロックしても、 その時点では既に画面の表示は終わっているという状態になってるので、 方法1よりも早く画面が表示されるのです。

この方法はとても簡単にできるので、よく使われている方法なのではないでしょうか。 かなり良い方法ではあるのですが、実はこの方法は完璧ではありません。 まだ改善の余地があります。 後述の方法3もしくは方法4を検討してみてください。

HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>

(省略:とっても長いHTML)// ①

<script src="/example1.js"></script> // ②
<script src="/example2.js"></script> // ③
</body>
</html>
pattern2.png

方法3:head タグの中で defer 属性を付けて読み込む

方法2は方法1よりも早く表示されるとはいえ、HTML パースが中断されることに変わりはありません。 そこで登場するのが、defer 属性です。 script タグに defer 属性を使用すると、HTML パースを中断させることなく、HTML パースと並行して JavaScript を読み込んでくれるようになります。

ブラウザは HTTP を使用して JavaScript ファイルをサーバーからダウンロードするわけですが、 ブラウザは HTTP のリクエストを送ったら、そのレスポンスが返ってくるまで、待つことしかやることが無いのです。 そこで、そのレスポンスが返ってくるまでの間に HTML をパースしてしまおうというアプローチです。 defer 属性を使用すると、HTML パースが中断しなくなるため、方法2よりもトータルの処理速度が速くなります。

しかも、JavaScript が実際に実行されるのは HTML パースの後になります。 つまり、DOM の構築が完了した後です。 そのため、DOMContentLoaded イベントを待つといった処理が必要なくなります。

「defer」は日本語で「延期」という意味です。 つまり、JavaScript ファイルの読み込みだけを先に済ませて、実行は HTML パースの後に延期してくれるのです。 複数の JavaScript ファイルがある場合は、これまでと同様に HTML に記述した順番で実行してくれます。 良いことづくめなのではないでしょうか。

なお、defer 属性を使用する場合は、script タグは head タグの中に置いた方が良いでしょう。 defer 属性を使用するのは、HTML パースを中断させることなく、HTML パースと並行して JavaScript を読み込んで、処理速度を上げることが目的です。 つまり、JavaScript ファイルへの HTTP リクエストを早く送ることができれば、並行で処理できる時間がそれだけ長くなるため効果的なのです。 方法2のように body タグの一番最後に置いたりしていると、並行で処理できる時間が無くなってしまい、defer 属性を使用する意味がなくなってしまうので注意してください。

HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script defer src="/example1.js"></script> // ①
<script defer src="/example2.js"></script> // ②
</head>
<body>

(省略:とっても長いHTML)// ③

</body>
</html>
pattern3.png

方法4:async 属性を付けて読み込む

方法3では処理速度を向上させるために、実行されるファイルの順番やタイミングが決まっていましたが、 そういった制約が全く必要ない JavaScript ファイルというのも存在します。 script タグに async 属性を使用すると、JavaScript ファイルが非同期で読み込まれるようになります。

script タグが見つかったタイミングで読み込みが開始されますが、非同期なので、どのタイミングで実行されるかわかりません。 JavaScript ファイルが早いタイミングでダウンロードされれば早いタイミングで実行されますし、遅いタイミングでダウンロードされれば遅いタイミングで実行されます。 複数の JavaScript ファイルがある場合の処理の順番も保証されません。 なお、JavaScript の実行中は HTML のパースは中断されます。

用途としては、他の JavaScript ファイルとの依存関係がなく、単体で実行されても問題がないものに利用します。 例えば、Google AdSense などの広告表示や、Google Analytics などのアクセス解析、Twitter などのシェアボタンやタイムラインの埋め込みなどが良い例です。

読み込まれた JavaScript はどんなタイミングで実行されるかわかりませんので、 どんなタイミングで実行されたとしても問題が無いような JavaScript ファイルにしておく必要があります。 場合によっては、DOM 構築の完了を待つために、方法2と同様に body タグの一番最後に置いたり、 jQuery を使用しているのであれば ready() に登録して呼ばれるのを待つなどの対応が必要になるかもしれません。

HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script async src="/example1.js"></script> // ①
<script async src="/example2.js"></script> // ②
</head>
<body>

(省略:とっても長いHTML)// ③

</body>
</html>
pattern4.png

まとめ

基本的には、head タグの中で defer 属性を付けて読み込むのが良いのではないでしょうか。

参考サイト

関連記事

最近、ダイアログを表示した際にページのスクロールを無効化する方法を探していて、思ったより苦戦したのですが、良い方法を見つけたので、忘れないように備忘録としてメモしておきます。誰かのお役に立てば幸いです。スクロールイベントはキャンセルできないまず最初にパッと思いついたのが、onscroll イベントハンドラーの中で pr ...
Twitter の埋め込みタイムラインを簡単に遅延読み込みさせる方法を思いついたので、備忘録としてメモしておきます。例として、Twitter の埋め込みタイムラインを使用していますが、他のサービスの埋め込みパーツでも同じ方法が使えると思います。誰かの参考になれば幸いです。Twitter の埋め込みタイムラインの問題点一 ...
最近のWebアプリでは、JavaScript を使ってがりがり処理することが多いです。動的にパラメータを渡して処理させることも多いのですが、うまく渡す方法を知らない人が意外と多いみたいです。なのでまとめてみます。誰かのお役にたてれば幸いです。前提説明しやすくするために下記の環境を想定します。文書型(DOCTYPE)HT ...

お知らせ

記事検索

最新記事

人気記事

RSSフィード

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(旧 Twitter) もしくは、お問い合わせより、お願いします。