CSS の読み込みによってブロックが発生しますか?

CSS の読み込みによってブロックが発生しますか?

おそらく誰もが js の実行によって DOM ツリーの解析とレンダリングがブロックされることを知っていると思いますが、CSS の読み込みによって DOM ツリーの解析とレンダリングがブロックされるのでしょうか?次に、CSS の読み込みが DOM ツリーの解析とレンダリングに与える影響をテストします。

このテストを完了するには、まずChromeを使用してダウンロード速度を設定する方法を学びましょう。

\1. Chromeコンソールを開く(F12キーを押す)と、次の図が表示されます。フォーカスは赤い円を描いた部分です。

赤い円 (スロットルなし) をクリックすると、次の画像が表示されます。GPRS オプションを選択します。

\2. 赤い丸(スロットリングなし)をクリックすると、次の画像が表示されます。GPRSオプションを選択します。

この方法では、リソースのダウンロード速度制限は 20kb/s に制限されます。それでは、本題に入りましょう。

3. このようにして、リソースのダウンロード速度の上限は 20kb/s に制限されます。それでは、本題に入りましょう。

CSS の読み込みにより、DOM ツリーの解析とレンダリングがブロックされますか?

コードについて話しましょう:

<!DOCTYPE html>
<html lang="ja">
  <ヘッド>
    <title>CSS ブロッキング</title>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1">
    <スタイル>
      h1 {
        色: 赤 !重要
      }
    </スタイル>
    <スクリプト>
      関数h(){
        コンソールログ(document.querySelectorAll('h1'))
      }
      タイムアウトを設定します(h, 0)
    </スクリプト>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="スタイルシート">
  </head>
  <本文>
    <h1>これは赤です</h1>
  </本文>
</html>

仮定: CSS の読み込みにより、DOM ツリーの解析とレンダリングがブロックされる

前提: bootstrap.css が読み込まれる前は、次のコンテンツは解析およびレンダリングされないため、最初に表示されるのは白い画面であり、h1 は表示されません。そして、この時点で console.log の結果は空の配列になるはずです。

実際の結果:以下の通り

CSS は DOM ツリーの解析をブロックしますか?

上の図から、CSSが読み込まれていない場合、h1は表示されませんが、コンソール出力は次のようになります。

この時点で、DOM ツリーは少なくとも h1 まで解析されていますが、CSS はまだロードされていないことがわかります。つまり、CSS は DOM ツリーの解析をブロックしません。

CSS の読み込みにより DOM ツリーのレンダリングがブロックされますか?

上の画像から、CSS が読み込まれていない場合、ページには白い画面が表示されることもわかります。赤いフォントは、CSS が読み込まれるまで表示されません。つまり、次のコンテンツは解析されますが、レンダリングされません。したがって、CSS の読み込みにより DOM ツリーのレンダリングがブロックされます。

このメカニズムに対する私の個人的な評価

実際、これはブラウザの最適化メカニズムでもあるのではないかと思います。 CSS をロードすると、次の DOM ノードのスタイルが変更される可能性があるためです。CSS のロードによって DOM ツリーのレンダリングがブロックされない場合は、CSS がロードされた後に DOM ツリーを再描画またはリフローする必要があり、不要な損失が発生する可能性があります。したがって、まず DOM ツリーの構造を解析し、実行可能な作業を実行し、CSS が読み込まれた後、最終的なスタイルに従って DOM ツリーをレンダリングします。このアプローチは、パフォーマンスの点で確かに優れています。

CSS の読み込みにより JS の実行がブロックされますか?

上記の推論から、CSS の読み込みは DOM ツリーの解析をブロックしないが、DOM ツリーのレンダリングをブロックすると結論付けることができます。それで、CSS の読み込みは JS の実行をブロックするのでしょうか?

もう一度、コードを通じてこれを確認します。

<!DOCTYPE html>
<html lang="ja">
  <ヘッド>
    <title>CSS ブロッキング</title>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1">
    <スクリプト>
      console.log('CSS 以前')
      var startDate = 新しい日付()
    </スクリプト>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="スタイルシート">
  </head>
  <本文>
    <h1>これは赤です</h1>
    <スクリプト>
      var endDate = 新しい日付()
      console.log('cssの後')
      console.log('経過時間' + (endDate - startDate) + 'ms')
    </スクリプト>
  </本文>
</html>

仮定: CSSの読み込みにより、後続のJSの実行がブロックされる

期待される結果: リンクの後の js コードは、CSS が読み込まれた後に実行される必要があります。

実際の結果:

上の図から、CSS 読み込みステートメントの前の js コードは最初に実行されますが、CSS 読み込みステートメントの後のコードは CSS が読み込まれるまで実行されないことがわかります。これは、CSS の読み込みによって後続の JS ステートメントの実行がブロックされることも示しています。詳細な結果については次の図を参照してください (CSS の読み込みには 5600 ミリ秒以上かかりました)。

結論は

上記から、次のような結論を導き出すことができます。

  • CSSの読み込みはDOMツリーの解析をブロックしません
  • CSSの読み込みによりDOMツリーのレンダリングがブロックされます
  • CSS を読み込むと、後続の JS ステートメントの実行がブロックされます。

したがって、ユーザーが長時間白い画面を目にすることを避けるためには、次の方法などを使用して、CSS の読み込み速度を可能な限り上げる必要があります。

  • CDN を使用する (CDN はネットワーク状況に基づいてリソースを提供するために、キャッシュされたコンテンツを持つ最も近いノードを選択するため、読み込み時間が短縮されます)
  • CSS を圧縮します (webpack、gulp などの多くのパッケージング ツールを使用するか、gzip 圧縮をオンにすることができます)
  • キャッシュを適切に使用してください (cache-control、expires、E-tag を設定することはすべて良いことですが、ファイルが更新された後はキャッシュの影響を避ける必要があることに注意してください。1 つの解決策は、ファイル名の後にバージョン番号を追加することです)
  • http リクエストの数を減らし、複数の CSS ファイルを結合するか、単にインラインで記述します (インライン スタイルの欠点の 1 つは、キャッシュできないことです)。

原理分析

では、なぜ上記のような現象が起こるのでしょうか?ブラウザのレンダリングプロセスから分析してみましょう。

ブラウザによって使用するカーネルが異なるため、レンダリング プロセスも異なります。現在、主なものは 2 つあります。

WebKit レンダリングプロセス

Gecko レンダリングプロセス

上記の 2 つのフローチャートから、ブラウザのレンダリング プロセスは次のようになることがわかります。

HTML ファイルを解析して DOM ツリーを生成し、CSS ファイルを解析して CSSOM ツリーを生成します。Dom ツリーと CSSOM ツリーを組み合わせてレンダリング ツリーを生成します。レンダリング ツリーに従ってレンダリングおよび描画し、ピクセルを画面にレンダリングします。

このプロセスからわかることは

  1. DOM 解析と CSS 解析は 2 つの並列プロセスであるため、CSS の読み込みによって DOM 解析がブロックされない理由もこれによって説明されます。
  2. ただし、レンダリング ツリーは DOM ツリーと CSSOM ツリーに依存しているため、レンダリングを開始する前に、CSSOM ツリーが構築される、つまり CSS リソースが読み込まれる (または CSS リソースの読み込みに失敗する) まで待機する必要があります。したがって、CSS の読み込みにより Dom レンダリングがブロックされます。
  3. js は以前の Dom ノードと css スタイルを操作する可能性があるため、ブラウザは html 内の css と js の順序を維持します。そのため、後続の js が実行される前にスタイルシートが読み込まれ、実行されます。したがって、CSS は後続の js の実行をブロックします。

DOMコンテンツが読み込まれました

ブラウザの場合、ページの読み込みには主に 2 つのイベントがあります。1 つは DOMContentLoaded で、もう 1 つは onLoad です。 onLoad については特に言うことはありません。ページのすべてのリソースが読み込まれた後にのみトリガーされます。これらのリソースには、CSS、JS、画像、ビデオなどが含まれます。

DOMContentLoaded は、その名前が示すように、ページのコンテンツが解析されるときにトリガーされます。上で説明したように、css は Dom のレンダリングと js の実行をブロックし、js は Dom の解析をブロックします。すると、次のような仮定を立てることができる。

  1. ページに CSS のみが存在する場合、または JS が CSS の前に配置されている場合、DomContentLoaded は CSS が読み込まれるまで待機する必要はありません。
  2. ページに CSS と JS の両方があり、JS が CSS の後ろにある場合、DomContentLoaded は CSS と JS の両方が読み込まれるまで待機してからトリガーされる必要があります。

まず最初のケースをテストしてみましょう:

<!DOCTYPE html>
<html lang="ja">
  <ヘッド>
    <title>CSS ブロッキング</title>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1">
    <スクリプト>
      document.addEventListener('DOMContentLoaded', 関数() {
        console.log('DOMコンテンツが読み込まれました');
      })
    </スクリプト>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="スタイルシート">
  </head>
  <本文>
  </本文>
</html>

実験結果を下の図に示します。

アニメーション画像から、CSS がロードされる前に DOMContentLoaded イベントがトリガーされたことがわかります。 CSS の背後に js コードがないためです。

次に、2 番目のケースをテストします。これは非常に簡単です。CSS の後に 1 行のコードを追加するだけです。

<!DOCTYPE html>
<html lang="ja">
  <ヘッド>
    <title>CSS ブロッキング</title>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1">
    <スクリプト>
      document.addEventListener('DOMContentLoaded', 関数() {
        console.log('DOMコンテンツが読み込まれました');
      })
    </スクリプト>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="スタイルシート">
​
    <スクリプト>
      console.log('もう私の番ですか?');
    </スクリプト>
  </head>
  <本文>
  </本文>
</html>

DOMContentLoaded イベントは、CSS の読み込みが完了した後にのみトリガーされることがわかります。したがって、次のように結論付けることができます。

ページに CSS と JS の両方があり、JS が CSS の後ろにある場合、CSS が読み込まれた後に DOMContentLoaded イベントが実行されます。 その他の場合、DOMContentLoaded は CSS の読み込みを待機せず、DOMContentLoaded イベントは画像やビデオなどの他のリソースの読み込みを待機しません。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

<<:  HTML テキストエスケープのヒント

>>:  SQLでEXPLAINコマンドを使用する方法

推薦する

Ubuntu で XFS ファイルシステム用の LVM を作成する方法

序文lvm (論理ボリューム マネージャー) 論理ボリューム管理は、Linux システムのニーズを満...

DOCTYPE 文書型宣言 (Web ページ愛好家必読)

DOCTYPE 宣言 作成するすべてのページの先頭に、ドキュメント宣言が必要です。はい、そうでしょう...

MySQLが内部一時テーブルを使用するタイミングについて簡単に説明します。

組合執行分析を簡単にするために、次のSQLを例として使用します。 テーブル t1 を作成します ( ...

Vue で親子コンポーネントの値を双方向バインドするために v-model を使用するときに発生する問題と解決策

目次シナリオ解決してみる解決するシナリオ今日、コンポーネントの双方向データバインディングにv-mod...

fullpage.js フルスクリーンスクロールの具体的な使い方

1.fullpage.js ダウンロードアドレスhttps://github.com/alvarot...

CentOS での Docker の詳細なインストール チュートリアル

DockerにはCEとEEがあり、CE版はコミュニティ版(無料)、EE版はセキュリティを重視したエン...

CSSアニメーションとSVGを組み合わせてエネルギーの流れの効果を作成する

最終的な効果は次のようになります。アニメーションは2つのステップに分かれていますランニング軌道を開発...

JavaScript による Web ページ カルーセルの超詳細な実装

目次HTML ページの作成js部分の機能を実装する1. 左ボタンと右ボタン2. 小さな円を動的に生成...

Bootstrap3.0 学習ノートテーブル関連

この記事では、Webサイトを作ったことがある人にとっては馴染みのあるテーブルについて主に説明します。...

Google 翻訳ツール: 多言語ウェブサイトを素早く実装

Google Chinaは、ウェブサイトやブログを素早く簡単に多言語化できる翻訳ツールをリリースした...

LinuxにMySQLをインストールし、外部ネットワークアクセスを構成する例

設定手順1. DNSが設定されているかどうかを確認するDNSが設定されていない場合は、前の記事を参照...

HTMLはa要素hrefのURLリンクを自動的に更新したり新しいウィンドウを開いたりする機能を実装する

場合によっては、次のような機能を実装したいことがあります。リンクをクリックします。リンクがブラウザで...

Win Server 2019 サーバーの IIS 構成と Web サイトの簡単な公開

1.まずサーバーにリモート接続する2. サーバーマネージャーを開く 3役割と機能の追加 4サーバープ...

auto.jsを使用して毎日の自動チェックイン機能を実現する

auto.js を使用して毎日のチェックインを自動化する感染症のせいで、毎日時間通りに家に帰らなけれ...

mysql-connector-java8.0.27 へのアップグレードに関する注意事項

最近、オンライン セキュリティ スキャンにより、MySQL コネクタに脆弱性が見つかりました。確認し...