Webページの読み込みと実行シーケンス?


244

私はいくつかのWebベースのプロジェクトを実行しましたが、通常のWebページのロードおよび実行シーケンスについてはあまり考えていません。しかし今、私は詳細を知る必要があります。GoogleやSOからの回答を見つけるのは難しいので、この質問を作成しました。

サンプルページは次のようになります。

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

だからここに私の質問があります:

  1. このページはどのように読み込まれますか?
  2. ロードのシーケンスは何ですか?
  3. JSコードはいつ実行されますか?(インラインおよび外部)
  4. CSSはいつ実行(適用)されますか?
  5. $(document).readyはいつ実行されますか?
  6. abc.jpgはダウンロードされますか?それともkkk.pngをダウンロードするだけですか?

私は次のことを理解しています。

  1. ブラウザは最初にhtml(DOM)をロードします。
  2. ブラウザは、外部リソースを上から下に1行ずつ読み込み始めます。
  3. a <script>が満たされている場合、読み込みはブロックされ、JSファイルが読み込まれて実行されるまで待機してから続行されます。
  4. その他のリソース(CSS /画像)は並列に読み込まれ、必要に応じて(CSSのように)実行されます。

それとも次のようですか?

ブラウザはhtml(DOM)を解析し、外部リソースを配列またはスタックのような構造で取得します。htmlが読み込まれた後、ブラウザは構造内の外部リソースの読み込みを並行して開始し、すべてのリソースが読み込まれるまで実行します。次に、JSに応じて、ユーザーの動作に応じてDOMが変更されます。

あなたがhtmlページの応答を得たときに何が起こるかについて誰かが詳細な説明をすることができますか?これはブラウザによって異なりますか?この質問についての参照はありますか?

ありがとう。

編集:

FirefoxでFirebugを使用して実験を行いました。そして、それは次の画像のように表示されます: 代替テキスト


11
スティーブ・スーダーズはこの分野で多くの仕事をしてきました。steve + souders + high + performanceのGoogleをご覧ください。
anddoutoi 2009年

3
パフォーマンスのチューニングという意味ではありません。詳細を知りたい。
朱タオ

2
彼の作品を読むことで、「それ」がどのように機能するかについての私の理解が10倍になり、それでも有効なコメントです。彼の本全体をここに引用することは著作権で許可されていないので、彼の作品を調べることをお勧めします。
anddoutoi 2009年

3
発生する順序についての詳細な説明はこちら
Gerrat

回答:


277

あなたのサンプルによると、

<html>
 <head>
  <script src="jquery.js" type="text/javascript"></script>
  <script src="abc.js" type="text/javascript">
  </script>
  <link rel="stylesheets" type="text/css" href="abc.css"></link>
  <style>h2{font-wight:bold;}</style>
  <script>
  $(document).ready(function(){
     $("#img").attr("src", "kkk.png");
  });
 </script>
 </head>
 <body>
    <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
    <script src="kkk.js" type="text/javascript"></script>
 </body>
</html>

おおよその実行フローは次のとおりです。

  1. HTMLドキュメントがダウンロードされます
  2. HTMLドキュメントの解析が始まります
  3. HTML解析の範囲 <script src="jquery.js" ...
  4. jquery.js ダウンロードされて解析されます
  5. HTML解析範囲 <script src="abc.js" ...
  6. abc.js ダウンロード、解析、実行
  7. HTML解析範囲 <link href="abc.css" ...
  8. abc.css ダウンロードされて解析されます
  9. HTML解析範囲 <style>...</style>
  10. 内部CSSルールが解析および定義されます
  11. HTML解析範囲 <script>...</script>
  12. 内部Javascriptが解析されて実行されます
  13. HTML解析の範囲 <img src="abc.jpg" ...
  14. abc.jpg ダウンロードして表示されます
  15. HTML解析の範囲 <script src="kkk.js" ...
  16. kkk.js ダウンロード、解析、実行
  17. HTMLドキュメントの解析が終了しました

ブラウザの動作により、ダウンロードが非同期でブロックされない場合があることに注意してください。たとえば、Firefoxでは、ドメインごとの同時リクエスト数を制限するこの設定があります。

また、コンポーネントがすでにキャッシュされているかどうかによって、近い将来のリクエストでコンポーネントが再度リクエストされない場合があります。コンポーネントがキャッシュされている場合、コンポーネントは実際のURLではなくキャッシュからロードされます。

解析が終了し、ドキュメントが準備されて読み込まれると、イベントonloadが発生します。したがって、onloadが起動されると、$("#img").attr("src","kkk.png");が実行されます。そう:

  1. ドキュメントの準備が整い、onloadが発生します。
  2. JavaScript実行ヒット $("#img").attr("src", "kkk.png");
  3. kkk.png ダウンロードされてロードされます #img

この$(document).ready()イベントは、実際には、すべてのページコンポーネントが読み込まれて準備ができたときに発生するイベントです。詳細については、http//docs.jquery.com/TutorialsIntroducing_ $(document).ready()をご覧ください。

編集-この部分は、平行部分または非部分について詳しく説明します。

デフォルトでは、私の現在の理解から、ブラウザーは通常、各ページをHTMLパーサー、JavaScript / DOM、CSSの3つの方法で実行します。

HTMLパーサーは、マークアップ言語の解析と解釈を担当するため、他の2つのコンポーネントを呼び出すことができる必要があります。

たとえば、パーサーがこの行に遭遇した場合:

<a href="#" onclick="alert('test');return false;" style="font-weight:bold">a hypertext link</a>

パーサーは2つのJavaScriptと1つのCSSへの3つの呼び出しを行います。最初に、パーサーはこの要素を作成し、この要素に関連するすべての属性とともにDOM名前空間に登録します。次に、パーサーはonclickイベントをこの特定の要素にバインドするために呼び出します。最後に、CSSスレッドをもう一度呼び出して、この特定の要素にCSSスタイルを適用します。

実行はトップダウンで、シングルスレッドです。JavaScriptはマルチスレッドに見えるかもしれませんが、実際のところ、JavaScriptはシングルスレッドです。これが、外部JavaScriptファイルをロードするときに、メインHTMLページの解析が一時停止される理由です。

ただし、CSSルールは常に適用されているため、CSSファイルは同時にダウンロードできます。つまり、要素は常に定義された最新のCSSルールで再描画されるため、ブロックが解除されます。

要素は、解析後にDOMでのみ使用できます。したがって、特定の要素を操作する場合、スクリプトは常にウィンドウのonloadイベントの後、またはウィンドウ内に配置されます。

次のようなスクリプトはエラーを引き起こします(jQueryで):

<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>
<div id="mydiv">Hello World</div>

スクリプトが解析されるとき、#mydiv要素はまだ定義されていないためです。代わりにこれはうまくいくでしょう:

<div id="mydiv">Hello World</div>
<script type="text/javascript">/* <![CDATA[ */
  alert($("#mydiv").html());
/* ]]> */</script>

または

<script type="text/javascript">/* <![CDATA[ */
  $(window).ready(function(){
                    alert($("#mydiv").html());
                  });
/* ]]> */</script>
<div id="mydiv">Hello World</div>

4
ありがとう。しかし、ブラウザの動作が原因で、ダウンロードが非同期でブロックされない可能性があるとおっしゃっていました。そのため、asynでどのようなコンポーネントをダウンロードできますか(インスタンスとしてFFを取得します)? <script>他のコンポーネントをブロックしますよね?各ブラウザの仕様についての参照はありますか?
朱タオ

4
$(document).ready()は、すべてのページコンポーネントが読み込まれたときではなく、DOMが完了したときに起動されます
Pierre

2
@Pierre by pageコンポーネント私はDOMを意味しました-> DOM内のすべてのコンポーネント。
モーリス2012年

3
明確にするために...通常のwindow.onloadは#17の後に発生します...したがって、jqueryの$(document).ready()のコードは何時に実行されますか?#12?しかし、DOM自体は#1でロードされますよね?
armyofda12mnkeys 2013年

1
<body>タブの場合、<img>タグと<script>タグの間に< link href = "bootstrap.min.css" rel = "stylesheet" />を追加すると、ブートストラップがダウンロードされるまでimgが表示されません...ステップ[13]、[14]に変更が必要だと思います...誰かがその動作を説明できますか?
Bhuvan、2015年

34

1)HTMLがダウンロードされます。

2)HTMLは段階的に解析されます。アセットのリクエストに到達すると、ブラウザはアセットのダウンロードを試みます。ほとんどのHTTPサーバーおよびほとんどのブラウザーのデフォルト構成では、2つの要求のみを並行して処理します。IEを再構成して、無制限の数のアセットを並行してダウンロードできます。Steve SoudersはIEで100を超えるリクエストを並行してダウンロードできました。例外は、スクリプトリクエストがIEの並列アセットリクエストをブロックすることです。このため、すべてのJavaScriptを外部JavaScriptファイルに入れ、HTMLのbody終了タグの直前にリクエストを置くことを強くお勧めします。

3)HTMLが解析されると、DOMがレンダリングされます。CSSは、ほぼすべてのユーザーエージェントでのDOMのレンダリングと並行してレンダリングされます。そのため、すべてのCSSコードを、ドキュメントの<head> </ head>セクションでできるだけ高く要求される外部CSSファイルに配置することを強くお勧めします。それ以外の場合、ページはDOM内のCSS要求位置が出現するまでレンダリングされ、レンダリングは最初からやり直します。

4)DOMが完全にレンダリングされ、ページ内のすべてのアセットに対するリクエストが解決されるか、タイムアウトした後にのみ、JavaScriptがonloadイベントから実行されます。IE7とIE8についてはよくわかりませんが、アセットリクエストからHTTP応答を受信しない場合、アセットがすぐにタイムアウトしません。つまり、JavaScriptがページにインラインで要求するアセット、つまり、関数に含まれていないHTMLタグにJavaScriptが書き込まれていると、onloadイベントが何時間も実行されないことがあります。このようなインラインコードがページに存在し、コードクラッシュを引き起こす名前空間の衝突が原因で実行に失敗した場合、この問題が発生する可能性があります。

上記のステップの中で最もCPUを集中的に使用するのは、DOM / CSSの解析です。ページをより高速に処理したい場合は、冗長な指示を削除し、CSS指示を可能な限り少ない要素参照に統合することにより、効率的なCSSを記述します。DOMツリーのノード数を減らすと、レンダリングが速くなります。

HTMLまたはCSS / JavaScriptアセットからリクエストする各アセットは、個別のHTTPヘッダーでリクエストされることに注意してください。これは帯域幅を消費し、リクエストごとの処理を必要とします。ページの読み込みをできるだけ速くしたい場合は、HTTPリクエストの数を減らし、HTMLのサイズを減らします。HTMLのみから180kでページの重みを平均化することによって、ユーザーエクスペリエンスを向上させることはありません。多くの開発者は、ユーザーが6ナノ秒でページのコンテンツの品質について自分で考え、不満がある場合はサーバーからDNSクエリを削除し、コンピューターを書き込みます。 250kのHTML。ユーザーがページをより速くロードできるように、HTMLは短く簡潔にしてください。


2
CSS指示を可能な限り少ない要素参照に統合すると、奇妙なサウンドになります。3つの要素のスタイルを設定する必要がある場合は、3つの要素を正確に参照する必要があります。スタイル10を参照することはできませんが、できますか?またはそれについて詳しく説明します
Green

12

Firefoxでページを開き、HTTPFoxアドオンを取得します。それはあなたが必要とするすべてを教えてくれます。

これはarchivist.incuitoで見つかりました:

http://archivist.incutio.com/viewlist/css-discuss/76444

最初にページをリクエストすると、ブラウザはGETリクエストをサーバーに送信し、サーバーはブラウザにHTMLを返します。次に、ブラウザはページの解析を開始します(おそらくすべてのページが返される前に)。

CSSファイル、画像ファイル、スクリプトファイル、Flashファイルなど、ページの外部にある(同じサーバー/ドメインにあるかどうかにかかわらず)外部エンティティへの参照が見つかると、そのリソースに対する追加のGETリクエスト。

ただし、HTTP標準では、ブラウザが同じドメインに対して3つ以上の同時リクエストを行わないように規定しています。そのため、特定のドメインへの各リクエストをキューに入れ、各エンティティが返されると、そのドメインのキューで次のエンティティを開始します。

エンティティが返されるまでにかかる時間は、エンティティのサイズ、サーバーで現在発生している負荷、ブラウザを実行しているマシンとサーバー間のすべてのマシンのアクティビティによって異なります。これらのマシンのリストは、1つの画像が大西洋を越えて米国から英国に移動し、同じサーバーから別の画像が太平洋、アジア、ヨーロッパを経由して出てくる場合、原則としてすべてのリクエストで異なる場合があります。時間がかかります。したがって、次のようなシーケンスが得られる可能性があります。この場合、ページには(この順序で)3つのスクリプトファイルと5つの画像ファイルへの参照があり、すべてサイズが異なります。

  1. GET script1およびscript2; script3およびimages1-5のキューリクエスト。
  2. script2が到着します(script1より小さい):GET script3、キューimages1-5。
  3. script1が到着します。GET image1、queue images2-5。
  4. image1が到着し、GET image2、キューimages3-5
  5. ネットワークの問題のため、script3が到着しません-script3を再度取得してください(自動再試行)。
  6. image2が到着し、script3はまだここにありません。GET image3、queue images4-5。
  7. 画像3が到着します。GET image4、queue image5、script3をまだ実行中です。
  8. image4が到着し、GET image5;
  9. image5が到着しました。
  10. script3が到着します。

つまり、サーバーが実行していること、インターネットの残りの部分が実行していること、および何かにエラーがあり、再フェッチする必要があるかどうかに応じて、古い注文があります。これは奇妙な方法のように思えるかもしれませんが、この方法で行わないと、インターネット(WWWだけでなく)がある程度の信頼性を持って動作することは文字通り不可能です。

また、ブラウザの内部キューは、ページに表示される順序でエンティティをフェッチしない場合があります。これは、標準では必須ではありません。

(ああ、ブラウザのキャッシュと、ネットワークの負荷を軽減するためにISPが使用するキャッシュプロキシの両方のキャッシュを忘れないでください。)



2

私の知る限り、ブラウザ(少なくともFirefox)はそれを解析するとすぐにすべてのリソースを要求します。imgタグを検出すると、imgタグが解析されるとすぐにその画像を要求します。そして、それは、HTMLドキュメントの全体を受け取る前でも可能です。つまり、HTMLドキュメントがダウンロードされても、HTMLドキュメントをダウンロードし続ける可能性があります。

Firefoxの場合、about:configでの設定に応じて、適用されるブラウザキューがあります。たとえば、同じサーバーから一度に8個を超えるファイルをダウンロードしようとはしません...追加のリクエストはキューに入れられます。ドメインごとの制限、プロキシごとの制限、およびその他のものがあると思います。これらは、Mozilla Webサイトに記載されており、about:configで設定できます。IEにはそのような制限がないとどこかで読んだことがあります。

メインのHTMLドキュメントがダウンロードされ、DOMが解析されるとすぐに jQuery readyイベントが発生します。次に、リンクされたすべてのリソース(CSS、画像など)がダウンロードされて解析された後、loadイベントが発生します。これはjQueryのドキュメントで明らかにされています。

すべてが読み込まれる順序を制御したい場合は、JavaScriptを使用するのが最も信頼できる方法だと思います。



1

選択した回答は、少なくともFirefox 52では最新のブラウザに適用されないように見えます。たとえば、css、javascriptなどのリソースをロードするリクエストは、HTMLパーサーが要素に到達する前に発行されることがわかりました。

<html>
  <head>
    <!-- prints the date before parsing and blocks HTMP parsering -->
    <script>
      console.log("start: " + (new Date()).toISOString());
      for(var i=0; i<1000000000; i++) {};
    </script>

    <script src="jquery.js" type="text/javascript"></script>
    <script src="abc.js" type="text/javascript"></script>
    <link rel="stylesheets" type="text/css" href="abc.css"></link>
    <style>h2{font-wight:bold;}</style>
    <script>
      $(document).ready(function(){
      $("#img").attr("src", "kkk.png");
     });
   </script>
 </head>
 <body>
   <img id="img" src="abc.jpg" style="width:400px;height:300px;"/>
   <script src="kkk.js" type="text/javascript"></script>
   </body>
</html>

CSSおよびJavaScriptリソースをロードするリクエストの開始時間がブロックされていないことがわかりました。FirefoxにはHTMLスキャンがあり、HTMLの解析を開始する前に主要なリソース(imgリソースは含まれていません)を特定しているようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.