インタビュアー: ユーザーがブラウザに URL を入力して Enter キーを押した後はどうなりますか?

 
  
 
  
 
  
您好,我是路人,更多优质文章见个人博客:http://itsoku.com

この質問はもう決まり文句で、面接の最後の質問としてよく使われます、ネット上にも記事がたくさんありますが、最近暇になったので自分でメモしてみたら、わかった気がしました今まで以上に徹底的に。

注: この記事の手順は、リクエストが単純な HTTP リクエストであり、HTTPS、HTTP2、最も単純な DNS、プロキシがなく、サーバーに問題がないという事実に基づいていますが、実際的ではありません。

大まかな流れ

  • URL解析

  • DNSクエリ

  • TCP接続

  • リクエストを処理する

  • 応答を受け入れる

  • ページをレンダリングする

1. URL解析

アドレス解決:

まず、入力された内容が正当なURLなのか、検索対象のキーワードなのかを判断し、入力内容に応じてオートコンプリートや文字エンコードなどの処理を行います。

HSTS

セキュリティ上の影響により、HSTS はクライアントに HTTPS の使用を強制してページにアクセスするために使用されます。

その他の操作

ブラウザは、セキュリティ チェックやアクセス制限などの追加の操作も実行します (以前は国内ブラウザは 996.icu に制限されていました)。

キャッシュをチェックする

2024a00ca6bd55b59a8c7a70b5440482.jpeg

2.DNSクエリ

基本的な手順

82a1cf4b8c2b133b569aa1afac09a3fa.png

1. ブラウザのキャッシュ

ブラウザはまずキャッシュにあるかどうかを確認し、キャッシュにない場合はシステム ライブラリ関数を呼び出してクエリします。

2. オペレーティング システムのキャッシュ

オペレーティング システムには独自の DNS キャッシュもありますが、その前にローカルの Hosts ファイルにドメイン名が存在するかどうかがチェックされ、存在しない場合はクエリ要求が DNS サーバーに送信されます。

3.ルーターキャッシュ

ルーターにも独自のキャッシュがあります。

4. ISP DNS キャッシュ

ISP DNS は、クライアント コンピュータに設定されている優先 DNS サーバーであり、ほとんどの場合、キャッシュがあります。

ルートネームサーバーの検索

前の手順がすべてキャッシュされていない場合、ローカル DNS サーバーはリクエストをインターネット上のルート ドメインに転送します。次の図は、プロセス全体をよく示しています。

fb9b0d79a2d4ea8da1392ae4df04e43d.jpeg

ルートネームサーバー (Wikipedia)

注意事項

再帰的方式:途中で戻らずに最後まで確認し、最終結果が得られた場合のみ情報を返す(ブラウザからローカルDNSサーバーまでの過程)

反復方式は、ローカル DNS サーバーからルート ドメイン ネーム サーバーにクエリを実行する方式です。

DNSハイジャックとは何ですか

フロントエンドDNSプリフェッチの最適化

3.TCP接続

TCP/IP は 4 つの層に分かれており、データを送信する場合、各層でデータをカプセル化する必要があります。

c6e446984dff78e42bc29556ed63e89c.jpeg

1. アプリケーション層: HTTP リクエストを送信します。

前の手順でサーバーの IP アドレスを取得しました。ブラウザは次のような HTTP メッセージの作成を開始します。

  • リクエストヘッダー (Request Header): リクエストメソッド、ターゲットアドレス、従うプロトコルなど。

  • リクエストボディ(その他のパラメータ)

注意点: ブラウザは GET メソッドと POST メソッドのみを送信でき、GET メソッドは Web ページを開くために使用されます。

2. トランスポート層: TCP がパケットを送信します。

トランスポート層はサーバーへの TCP 接続を開始し、サーバーが受信時にメッセージ情報を正確に復元できるように、送信を容易にするためにデータが (メッセージ セグメントの単位で) 分割され、番号が付けられます。

接続を確立する前に、まず TCP スリーウェイ ハンドシェイクが実行されます。

TCP/IP の 3 ウェイ ハンドシェイクについては、インターネット上にすでに多くの文章や写真があり、それを生き生きと説明しているので、それを見てみることができます。

3. ネットワーク層: IP プロトコルのクエリ Mac アドレス

データ セグメントをパックし、送信元 IP アドレスと宛先 IP アドレスを追加して、送信ルートを検索します。

ターゲット アドレスが現在のアドレスと同じネットワーク内にあるかどうかを確認します。そうである場合は、Mac アドレスに従って直接送信します。そうでない場合は、ルーティング テーブルを使用してネクスト ホップ アドレスを見つけ、ARP プロトコルを使用してその Mac アドレスを照会します。

注: OSI 参照モデルでは、ARP プロトコルはリンク層にありますが、TCP/IP ではネットワーク層にあります。

4. リンク層: イーサネットプロトコル

イーサネットプロトコル

イーサネット プロトコルによれば、データは「フレーム」単位のデータ パケットに分割され、各フレームは次の 2 つの部分に分割されます。

  • ヘッダー: 送信者、受信者、パケットのデータ型

  • データ: データパケットの特定の内容

Macアドレス

イーサネットでは、ネットワークに接続されているすべてのデバイスが「ネットワーク カード」インターフェイスを備えている必要があり、データ パケットは 1 つのネットワーク カードから別のネットワーク カードに渡されると規定されており、ネットワーク カードのアドレスは Mac アドレスです。各 Mac アドレスは一意であり、1 対 1 の機能を持ちます。

放送

データの送信方法は非常に原始的です。データは ARP プロトコルを通じてネットワーク内のすべてのマシンに直接送信されます。受信側はヘッダー情報を自分の Mac アドレスと比較し、一致する場合は受信し、一致しない場合は破棄します。

注: 受信側の応答はユニキャストです。

サーバーはリクエストを受け入れます

承認プロセスは上記の手順を逆に実行します。上の図を参照してください。

4 番目に、サーバーがリクエストを処理します。

大まかな流れ

238e6f3a67c4fe2f0b4fe8d658f2a7c0.jpeg

HTTPD

最も一般的な HTTPD は、Linux では一般的に使用される Apache と Nginx、Windows では IIS です。

リクエストをリッスンし、リクエストを処理するために子プロセスを開始します。

対処する

TCP メッセージを受信すると、接続を処理し、HTTP プロトコル (リクエスト メソッド、ドメイン名、パスなど) を分析し、いくつかの検証を実行します。

  • 仮想ホストが構成されていることを確認する

  • 仮想ホストがこのメソッドを受け入れることを確認します。

  • ユーザーがメソッドを使用できることを確認します (IP アドレス、ID 情報などに基づいて)。

リダイレクト

サーバーに HTTP リダイレクトが設定されている場合、サーバーは永続的なリダイレクト応答を返し 301、ブラウザーはその応答に従って HTTP リクエストを再送信します (上記のプロセスを再実行します)。

URL書き換え

次に、URL 書き換えルールをチェックし、要求されたファイルが画像、html、css、js ファイルなどの実際のファイルである場合は、ファイルを直接返します。それ以外の場合、サーバーはルールに従ってリクエストを RESTful URL に書き換えます。次に、動的言語のスクリプトに従って、リクエストを処理するためにどの種類の動的ファイル インタプリタを呼び出すかが決定されます。

PHP 言語の MVC フレームワークを例にとると、まずいくつかの環境パラメーターを初期化し、URL に従ってルートを上から下に照合し、次にルートによって定義されたメソッドにリクエストを処理させます。

5. ブラウザは応答を受け取ります

ブラウザはサーバーから応答リソースを受信すると、そのリソースを分析します。

まず応答ヘッダーを確認し、さまざまなステータス コード (前述のリダイレクトなど) に応じてさまざまな処理を実行します。

応答リソースが圧縮されている場合 (gzip など)、解凍する必要もあります。

次に、応答リソースをキャッシュします。

次に、応答リソースの MIME[3] タイプに従って応答コンテンツを解析します (たとえば、HTML と画像では解析方法が異なります)。

6. ページをレンダリングする

ブラウザカーネル

e272c42984b09eda07250272044b7a41.jpeg

ブラウザ カーネルが異なればレンダリング プロセスも異なりますが、一般的なプロセスは似ています。

基本的なプロセス

4192253c8aa26e21633d5b3aa3219bbd.jpeg

6.1. HTML の解析

まず第一に、ブラウザの解析は上から下まで 1 行ずつ解析されることを知っておく必要があります。

解析プロセスは 4 つのステップに分けることができます。

①デコード(エンコード)

実際に送り返されるのはバイナリ バイト データであり、ブラウザはそれをファイルの指定されたエンコード (UTF-8 など) に従って文字列、つまり HTML コードに変換する必要があります。

② 事前解析(事前解析)

img事前解析では、処理時間を短縮するために事前にリソースをロードし、ラベル属性などのリソースを要求するいくつかの属性を識別し、srcこの要求を要求キューに追加します。

③トークン化

トークン化は、入力をシンボルに解析する字句解析のプロセスです。HTML シンボルには、開始タグ、終了タグ、属性名、属性値が含まれます。

ステート マシンを使用してシンボルの状態を識別します (たとえば、 に遭遇すると<>状態が変化します)。

④ツリー構築

注: ツリーのシンボル化と構築は並行して実行されます。つまり、開始タグが解析されるとすぐに DOM ノードが作成されます。

トークン化の前のステップで、パーサーはこれらのトークンを取得し、適切な方法でオブジェクトを作成しDOM、これらのトークンをDOMオブジェクトに挿入します。

<html><head><title>Web page parsing</title></head><body><div><h1>Web page parsing</h1><p>This is an example Web page.</p></div></body></html>
acb32da59772e607294e5b8d50664682.jpeg

ブラウザのエラー耐性

ブラウザで「無効な構文」エラーが発生するのは見たことがありません。これは、ブラウザが不正な構文を修正して動作し続けるためです。

イベント

解析プロセス全体が完了すると、ブラウザはイベントを通じて解析の完了をDOMContentLoaded通知します。DOM

6.2. CSS の解析

ブラウザが CSS をダウンロードすると、CSS パーサーは検出した CSS を処理し、文法仕様 [4] に従ってすべての CSS を解析してトークン化し、ルール テーブルを取得します。

CSS マッチング ルール

ノードに対応する CSS ルールと一致する場合、右から左の順序で行われます。たとえば、最初にすべてのタグがdiv p { font-size :14px }検索され、次にその親要素が であるかどうかが判断されますpdiv

したがって、CSS を記述するときは、ID とクラスを使用するようにし、過度にカスケードしないようにしてください。

6.3. レンダリングツリー

実際、これは DOM ツリーと CSS ルール ツリーをマージするプロセスです。

display:none注: レンダリング ツリーは、設定されているノードなど、レンダリングする必要のないノードを無視します。

計算する

サイズ値は、へのauto変換などの計算によって、 、パーセント、ピクセルの 3 つの可能性のいずれかに縮小されますrempx

カスケード

ブラウザは、対応する要素に実際にどのスタイルを適用する必要があるかを判断する方法を必要とするため、specificity次のような式を使用します。

  • タグ名、クラス、ID

  • スタイルをインライン化するかどうか

  • !important

次に、重量値を取得し、最も高い値を選択します。

レンダリングのブロック

タグが見つかるとscript、スクリプトの実行が終了するまで DOM 構築が一時停止され、その後 DOM ツリーの構築が続行されます。

ただし、JS が CSS スタイルに依存しており、それがダウンロードされて構築されていない場合、ブラウザーは CSS ルールが構築されるまでスクリプトの実行を遅らせます。

私たちが知っていることは次のとおりです。

  • CSS は JS の実行をブロックします

  • JS は後続の DOM 解析をブロックします

この状況を回避するには、次の原則に従う必要があります。

  • CSS リソースは JavaScript リソースの前にソートされます

  • JS は HTML の下部、つまり </body>HTML の前に配置されます。

さらに、ブロック モードを変更したい場合は、遅延と非同期を使用できます。

6.4. レイアウトと描画

レンダリング ツリー内のすべてのノードの位置、サイズなどの幾何学的プロパティを決定し、最後にボックス モデルを入力します。これにより、画面上の各要素の正確な位置とサイズを正確にキャプチャできます。

次に、レンダー ツリーが走査され、レンダラーのペイント() メソッドを呼び出してその内容が画面に表示されます。

6.5. レンダーレイヤーの結合

上で描いた絵をすべて結合し、最終的に絵を出力します。

6.6. リフローと再描画

リフロー

htmlブラウザは、特定の部分の変更がレイアウトに影響を与えていることを検出すると、ラベルから再帰的に位置とサイズを再計算し、戻って再レンダリングする必要があります。

マウスをスライドしてウィンドウのサイズを変更すると、ページが変更されるため、リフローは基本的に避けられません。

塗り直す

再描画は、要素の背景色や文字色などを変更しても、周囲の要素の位置の変更に影響を与えない場合に発生します。

再描画するたびに、ブラウザはレンダリング レイヤを結合して画面に出力する必要もあります。

リフローのコストは再描画よりもはるかに高いため、リフローを避けるように努める必要があります。

たとえば、display:none リフローはトリガーされますが、 visibility:hidden 再描画のみがトリガーされます。

6.7. JavaScriptのコンパイルと実行

大まかな流れ

463fbd00cba18bc0fd32f177a32d7454.jpeg

それは 3 つの段階に分けることができます。

1. 字句解析

JS スクリプトがロードされると、まず構文解析段階に入り、コード ブロックの構文が正しいかどうかを解析し、正しくない場合は「文法エラー」をスローして実行を停止します。

いくつかの手順:

  • たとえば、単語の分割では、を、 、などの語彙単位var a = 2に分割します。vara=2

  • 解析。トークンを抽象構文ツリー (AST) に変換します。

  • コード生成。抽象構文ツリーを機械語命令に変換します。

2. プリコンパイル

JS には 3 つの実行環境があります。

  • 地球環境

  • 機能環境

  • 評価

異なる動作環境に入るたびに、対応する実行コンテキストが作成されます。異なるコンテキストに従って、関数呼び出しスタックが形成されます。スタックの一番下は常にグローバル実行コンテキストであり、スタックの一番上は常にグローバル実行コンテキストになります。現在の実行コンテキスト。

実行コンテキストの作成

実行コンテキストを作成するプロセスでは、主に次の 3 つのことが行われます。

  • 変数オブジェクトを作成する

  • パラメータ、関数、変数

  • スコープチェーンを作成する

  • 現在の実行環境が変数にアクセスできるか確認する

  • これが次のことを指していることを確認してください

3. 実行

JSスレッド

50ff23aeb91bff37948ab54137594bc6.jpeg

JS はシングルスレッドですが、実際には 4 つのスレッドが作業に関与します。

そのうち 3 つは単なる補助であり、実際に実行されるのは JS エンジン スレッドのみです

そのうち 3 つは単なる補助であり、実際に実行されるのは JS エンジン スレッドのみです

JS エンジン スレッド: JS カーネルとも呼ばれ、V8 エンジン イベント トリガー スレッドなど、JS スクリプト プログラムのメイン スレッドの解析と実行を担当します。ブラウザ カーネル スレッドに属し、主にマウス、キーボードなどのイベントを制御するために使用されます。イベントがトリガーされると、イベント処理関数がイベント キューにプッシュされ、JS エンジン スレッドがタイマー トリガー スレッド (メイン コントロールであり、タイミングに使用されます) を実行するのを待ちます。タイミングが終了すると、タイマー処理関数が実行されsetIntervalますsetTimeout。イベントキューにプッシュされ、JS エンジンスレッドを待ちます。HTTP 非同期リクエスト スレッド: XMLHttpRequest を通じて接続した後、ブラウザーによって開かれた新しいスレッドを通じて、readyState 状態の変化を監視するときに、この状態のコールバック関数が設定されている場合、この状態の処理関数がイベントにプッシュされます。キューに入れて、JS エンジン スレッドの実装を待ちます。

注: 同じドメイン名に対するブラウザの同時接続数は制限されており、通常は 6 です。

マクロタスク

に分け:

  • 同期タスク: 順番に実行します。前のタスクが完了した後にのみ、次のタスクを実行できます。

  • 非同期タスク: 直接実行されるのではなく、トリガー条件が満たされた場合にのみ、関連するスレッドが非同期タスクをタスクキューにプッシュし、非同期 Ajax などの JS エンジンのメインスレッドでタスクの実行が完了するのを待ちます。 、DOM イベント、setTimeout など。

マイクロタスク

マイクロタスクは ES6 および Node 環境下にあり、主な API は次のとおりPromiseですprocess.nextTick

マイクロタスクは、マクロタスクの同期タスクの後、非同期タスクの前に実行されます。

f629ee253e96b1de08d255c6d016997e.jpeg

コード例

console.log('1'); // 宏任务 同步
setTimeout(function() {
 console.log('2');  // 宏任务 异步})
new Promise(function(resolve) {
 console.log('3');  // 宏任务 同步    
 resolve();
}).then(function() {
 console.log('4')// 微任务})
 console.log('5') // 宏任务 同步

上記のコード出力シーケンスは 1,3,5,4,2 です。

59a22153df7f288c0b064ea53d140d24.png

↓ クリックすると原文が読め、個人ブログへジャンプします

079ca126083350a1f69e23b240af25b5.jpeg 見てますか

おすすめ

転載: blog.csdn.net/likun557/article/details/131714400