JavaScriptとは②

2023/03/09に公開約4,500字

MDN( https://developer.mozilla.org/ja/docs/Web/JavaScript
を参考に勉強するように注意が入ったので、こらを教本にしていきます。
その為、抜粋しながら進めたいと思います。

スクリプトの読み込み方針

スクリプト[1]を適切なタイミングで読み込むためには、いくつかの問題があります。
一般的な問題は、ページ上のすべての HTML が、現れた順に読み込まれることです。 JavaScript を使用してページ上の要素を操作する場合、何かをしようとする対象の HTML よりも前に JavaScript が読み込まれて解釈されても、コードは動作しません。

前回の内部の例と外部の例では、HTML 本文が解釈される前に JavaScript が読み込まれて文書の head で実行されています。 これによりエラーが発生する可能性があるため、いくつかの構文を使用して回避しています。

内部の例では、こちら。

document.addEventListener('DOMContentLoaded', () => {
・・・
});

これはブラウザーの DOMContentLoaded イベントを待ち受けするイベントリスナーで、 HTML の本体が完全に読み込まれて解釈されたことを示します。このブロック内の JavaScript は、そのイベントが発生するまで実行されないため、エラーは回避されます。

DOMContentLoaded

Document Object Model(=DOM、ドキュメントオブジェクトモデル)はHTML や XML 文書を取り扱うための API。
『DOMContentLoaded』イベントはDOMの読み込みと解析が完了してから起動し、画像やCSS、JavaScriptの読み込みが完了するのを待たないで行われる。

外部の例(html.js)では、こちら。

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

より現代的な JavaScript 機能の defer 属性を使用して問題を解決し、
<script> 要素[2]になった後も HTML コンテンツのダウンロードを続行するようブラウザーに指示します。
この場合、スクリプトと HTML の両方が同時に読み込まれ、コードが機能します。

この問題に対する昔ながらの解決策は、すべての HTML が解釈された後に読み込まれるように、 body の下部に(たとえば </body> タグの直前に) script 要素を置くことでした。 この解決の問題点は、HTML DOM が読み込まれるまでスクリプトの読み込みと解釈が完全にブロックされることです。
JavaScript がたくさんある大規模なサイトでは、これは大きなパフォーマンス上の問題を引き起こす可能性があり、サイトを遅くします。

async(エイシンク)とdefer(デファー)

実際には、スクリプトのブロッキングの問題を回避できる現代的な機能が2つあります。『async』 と 『defer』です。
これらの2つの違いを見てみましょう。

async, deferをつけない場合

  • HTML Parser中にscriptタグが見つかる。
    HTML Parserを中断
    →scriptをダウンロードする。
    →scriptを実行する。
    →HTML Parserを再開する

async属性

  • ページをブロックすることなくスクリプトをダウンロードする。 ダウンロードが完了すると、スクリプトが実行され、ページのレンダリング[3]がブロックされる。
  • 複数のスクリプトが特定の順序で実行されるという保証はない。
  • ページ内のスクリプトが互いに独立して実行され、ページ内の他のスクリプトに依存しない場合は、 asyncを使用するのが最もよい方法です。

たとえば、次のスクリプト要素があるとします。

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

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

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

スクリプトが読み込まれる順序に頼ることはできません。
jquery.js が読み込まれるのは script2.js と script3.js よりも前かもしれませんし、後かもしれません。
この場合、これらのスクリプトの関数が jquery に依存していると、スクリプトの実行時に jquery が定義されないため、エラーが発生します。
読み込むバックグラウンドスクリプトがいくつもあって、それらをできるだけ早く実行したい場合にasyncを使用。

  • HTML Parser中にscriptタグが見つかる。
    scriptはダウンロードされる。HTML Parserは継続。
    →scriptのダウンロードが完了。
    →HTML Parserを中断する。
    →scriptを実行する。
    →HTML Parserを再開する。

defer属性

  • defer属性で読み込まれたスクリプトは、ページに表示されている順番に読み込まれる。
  • ページのコンテンツがすべて読み込まれるまで実行されない。
  • スクリプトがDOMに依存している場合に便利。

たとえば、次のスクリプト要素があるとします。

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

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

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

ページに現れた順序でスクリプトを実行し、スクリプトとコンテンツが読み込まれるとすぐにスクリプトを実行します。
defer属性を持つすべてのスクリプトは、ページに現れた順序で読み込まれます。
したがって、jquery.js → script2.js → script3.js の順に読み込まれることは確実です。
ページコンテンツがすべて読み込まれるまでは、実行せず、これはスクリプトがDOM配置に依存している場合に便利です(例: ページの要素を変更する場合)。

  • HTML Parser中に scriptが見つかる。
    scriptがダウンロードされる。HTML Parserは継続。
    →scriptのダウンロードが完了。HTMLパーサーは継続。
    →HTML Parserが完了。
    →scriptを実行する。

要約

  • async と defer のどちらも、ページのその他の部分(DOMなど)と並行して、ブラウザーにスクリプトを別スレッドでダウンロードするよう指示するので、読み取りの過程で読み取りプロセスがブロックされることはなくなります。
  • async属性を付けたスクリプトは、ダウンロードが完了し次第、すぐに実行されます。 これはページをブロックし、特定の実行順序を保証することはありません。
  • defer属性を付けたスクリプトは、出現順に読み込まれ、すべての読み込みが終了した後に実行。
  • スクリプトを直ちに実行するべきであり、依存関係がない場合は、『async』を使用。
  • スクリプトが解釈を待つ必要があり、他のスクリプトやDOM上の位置に依存する場合は、 『defer』を使用して読み込み。対応する <script> 要素をブラウザーに実行させたい順に配置。
脚注
  1. スクリプト(script)とはプログラムの種類の一つで、人間が読み書きしやすいプログラミング言語で書かれたプログラム(ソースコード)を簡単に解釈実行できるようにした、簡易なコンピュータプログラムのことです。
    ※ソフトウェアの設計など、コンピュータに命令を与える際には、通常、人間が普通に読み書きできる言語から、コンピュータが理解できる言語、いわゆる機械語への変換が必要です。 ↩︎

  2. script要素は、JavaScriptの埋め込みを表し、ブラウザ上には表示されません。外部JavaScriptファイルを読み込んだり、ページに直接JavaScriptを記述する場合に使用します。 ↩︎

  3. レンダリング(rendering)とは、あるデータを処理または演算することで画像や映像を表示させることです。 動画制作などにおいては、さまざまな形式のデータに処理を加えることによって、映像や画像や音声などを生成する作業を指します。 ↩︎

Discussion

ログインするとコメントできます