ページ全体がロードされる前にJavaScriptを実行できますか?


96

ページ全体がロードされる前に、JavaScriptを少し実行したいと思います。これは可能ですか?または、コードは実行を開始し</html>ますか?



2
私はそれが重複しているとは思わない-それはサーバーとクライアントの通信の質問のより多くです。
scunliffe

回答:


186

だけでなくすることができますが、あなたは特別な努力をしなければならないあなたがしたくない場合に。:-)

ブラウザーはscript、HTMLの解析中にクラシックタグを検出すると、解析を停止し、スクリプトを実行するJavaScriptインタープリターに引き渡します。スクリプトの実行が完了するまで、パーサーは続行しません(スクリプトがdocument.writeパーサーが処理する必要がある出力マークアップを呼び出す可能性があるため)。

これがデフォルトの動作ですが、スクリプトの実行を遅らせるオプションがいくつかあります。

  1. JavaScriptモジュールを使用します。type="module"スクリプトがされて延期 HTMLが完全に解析されており、初期のDOMが作成されるまで。これはモジュールを使用する主な理由ではありませんが、それが理由の1つです。

    <script type="module" src="./my-code.js"></script>
    <!-- Or -->
    <script type="module">
    // Your code here
    </script>
    

    コードは(別個の場合)フェッチされ、HTML解析と並行して解析されますが、HTML解析が完了するまで実行されません。(モジュールコードが独自のファイル内ではなくインラインの場合、HTML解析が完了するまで延期されます。)

    これは2010年に最初にこの回答を書いたときは利用できませんでしたが、ここ2020年には、すべての主要な最新のブラウザーがモジュールをネイティブでサポートします。古いブラウザーをサポートする必要がある場合は、WebpackやRollup.jsなどのバンドラーを使用できます。

  2. defer従来のスクリプトタグで属性を使用します。

    <script defer src="./my-code.js"></script>

    モジュールと同様に、のコードはmy-code.js、HTML解析と並行してフェッチおよび解析されますが、HTML解析が完了するまで実行されません。ただしdeferはインラインスクリプトコンテンツでは機能せず、を介して参照される外部ファイルでのみ機能しますsrc

  3. 私はそれがあなたが望んでいることだとは思いませんasyncが、HTML解析と並行してJavaScriptコードをフェッチするようにブラウザに指示する属性を使用できますが、HTML解析が完了していなくても、できるだけ早く実行することができます。あなたは上に置くことができtype="module"、タグ、またはその代わりにそれを使用するdefer古典にscriptタグ。

  4. 置くscript直前決算に、文書の最後にタグを</body>タグ:

    <!doctype html>
    <html>
    <!-- ... -->
    <body>
    <!-- The document's HTML goes here -->
    <script type="module" src="./my-code.js"></script><!-- Or inline script -->
    </body>
    </html>
    

    このようにして、コードが検出されるとすぐに実行されますが、その上のHTMLによって定義されたすべての要素が存在し、使用できるようになります。

    一部のブラウザーでは、scriptタグが検出されるまでコードのフェッチを開始しなかったため、これにより追加の遅延が発生していましたが、最新のブラウザーは先をスキャンしてプリフェッチを開始していました。それでも、これは現時点で3番目の選択肢であり、どちらのモジュールdeferも優れたオプションです。

スペックは有用図有する生を示すscriptタグを、deferasynctype="module"、およびtype="module" asyncJavaScriptコードがフェッチされ実行されるときのタイミングと:

ここに画像の説明を入力してください

次に、デフォルトの動作の例である未加工scriptタグを示します。

.found {
    color: green;
}
<p>Paragraph 1</p>
<script>
    if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

(そのコードの詳細については、ここの私の答えを参照してくださいNodeList。)

これを実行すると、「段落1」は緑色で表示されますが、「段落2」は黒色です。これは、スクリプトがHTML解析と同期して実行されたため、最初の段落のみが検出され、2番目の段落は検出されなかったためです。

対照的に、これがtype="module"スクリプトです。

.found {
    color: green;
}
<p>Paragraph 1</p>
<script type="module">
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

現在、どちらも緑になっていることに注目してください。HTML解析が完了するまで、コードは実行されませんでした。これはdefer script、外部コンテンツ(インラインコンテンツではない)にも当てはまります。

NodeListモジュールをサポートする最新のブラウザーはすでにforEachオンになっているため、そこでチェックする必要はありませんでしたNodeList。)

この現代の世界では、DOMContentLoadedPrototypeJS、jQuery、ExtJS、Dojo、およびその他のほとんどが当時提供していた(まだ提供している)「準備完了」機能のイベントに真の価値はありません。モジュールまたはを使用してくださいdefer。でも戻っ日で、それらを使用するための多くの理由がありませんでした(と彼らはしばしばので、全体のjQueryライブラリをロードしている間にページのプレゼンテーションを持ち上げ、不正に使用されたscriptにあったhead何か、文書の後の代わりに)で一部の開発者は、 Googleは早い段階でフラグを立てました。これも、YUIがの最後にスクリプトを配置すること推奨した理由の一部でしたbody


1
@FeRD-編集ありがとうございます。レビューアーはそれを拒否しましたが、あなたはまったく正しかったです。:-)
TJクラウダー

または、すべてを関数に入れて、に入れ<body onload="doIt()>"ます。
Justin Liu

@JustinLiu- loadイベントはページのロードサイクルの非常に遅く発生します。それまでJavaScriptの実行を待機することは、ほとんどの場合ベストプラクティスではありません。しかし、はい、それはオプションです。私は2020年の回答を全面的に見直しました。
TJクラウダー

または、次のように使用できますdocument.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
Justin Liu

@JustinLiu-うん、最後の段落を見てください。:-)私は必要性を見たことがありませんが、あなたはそうすることができます。
TJクラウダー

6

JavaScriptコードはいつでも実行できます。AFAIKは、ブラウザが<script>タグがある場所に到達したときに実行されます。ただし、まだロードされていない要素にはアクセスできません。

したがって、要素へのアクセスが必要な場合は、DOMが読み込まれるまで待つ必要があります(これは、画像やその他のものを含め、ページ全体が読み込まれることを意味するわけではありません。これは、ドキュメントの構造だけであり、はるかに早く読み込まれるため、通常はjQueryのDOMContentLoadedようなイベントまたは関数を使用して、遅延に気付かないでください$.ready


2
DOMContentLoadedイベントは、DOM階層が完全に構築されるとすぐに発生し、すべての画像とサブフレームの読み込みが完了すると、loadイベントが発生します。
BeauCielBleu 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.