【JavaScript】JavaScript、その前に〜Webサイトが表示されるまで・レンダリング

JavaScriptの勉強に必要な事前知識です。追求すると底がありませんが、最低限必要な内容をまとめました。

- Webページが表示されるまでの流れ
- ブラウザの役割
- JavaScriptの役割

# Webサイトが表示されるまで
アドレスバーにURLを入力し、画面上にWebページが表示されるまでの流れです。通信でどのようなデータがやり取りされているか、確認しておきます。

## 図解
![HTTP通信.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201515/dd495f80-3f63-bce6-5c67-ab8dcb11bb7a.png)

# ブラウザ
上図のクライアントに該当するアプリケーションが``ブラウザ``です。動作の結果は「Webページを表示する」ですが、内部では様々なことが行われています。

ブラウザの構成については、意外とネット上の情報が少なかったです。
自分は下記サイトを参考にしました。

> [ブラウザの仕組み: 最新ウェブブラウザの内部構造](https://www.html5rocks.com/ja/tutorials/internals/howbrowserswork/#The_browser_)
> [ウェブサイトが表示されるまでにブラウザはどういった仕事を行っているのか？](https://gigazine.net/news/20190624-how-web-works/)

明確に構造が分かれているかは分かりませんが、少なくとも理解しやすくなるかと思います。

## 構成
### ユーザーインターフェイス (UI)
アドレスバーや戻る/進むボタン、ブックマークメニューなど、ブラウザ画面のうち要求したページが表示されるメインウィンドウを除くすべての部分です。

### ブラウザエンジン
ユーザーインターフェイスとレンダリングエンジン間で、情報の受け渡しをします。

### レンダリングエンジン
レスポンスのボディ(本文)から``リソース(HTMLファイルやCSSファイル、画像データなど)``を受け取った後、構文を解析し画面にテキストと画像を描画します。

### ネットワーキング
主としてHTTPによりサーバと通信し、コンテンツを取得します。

### JavaScriptエンジン
JavaScriptコードの解析と実行を行います。

### UIバックエンド
チェックボックスやウィンドウなどのコアウィジェット(クライアントがWebページ上で操作を行うための部品)を描画します。

### データストレージ
Cookieなど、Webページで扱うデータを保存します。

HTML5でブラウザ内の軽量なデータベースである``ウェブストレージ(Web Storage)``が定義されました。ウェブストレージは``セッションストレージ(Window.sessionStorage)``と``ローカルストレージ(Window.localStorage)``の二種類があります。

これらのストレージは[API(Storageインターフェイス)](https://developer.mozilla.org/ja/docs/Web/API/Storage)が提供されています。

## 代表的なブラウザ
| ブラウザ    | レンダリングエンジン|JavaScriptエンジン|
|:-----------------|:---------------|:---------------|
| Google Chrome    |          Blink |        V8     |
| Opera            |          Blink |       V8      |
| Safari           |         WebKit |        Nitro  |
| Firefox          |          Gecko |   SpiderMonkey |
| Microsoft Edge   |       EdgeHTML |       Chakra   |
| Internet Explorer|        Trident |      Chakra    |

## 参考リンク

- [HTTPのメッセージ](https://developer.mozilla.org/ja/docs/Web/HTTP/Messages)
- [「HTTPリクエスト」と「HTTPレスポンス」](https://itsakura.com/network-http-get-post)
- [Webブラウザ、レンダリングエンジン、JavaScriptエンジンを整理して図視化してみた](https://qiita.com/umashiba/items/8cb47825624c5cb043d6)

# レンダリング
レスポンスを受け取った後、ブラウザで画面表示されるまでの流れです。

1. Download
2. Perse
3. Scripting
4. Style
5. Layout
6. Paint
7. Rasterize
8. Composite Layers

## 図解
![レンダリング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201515/01882f94-9f1d-90fa-013e-5f8251b57870.png)

## 工程
ブラウザの``レンダリングエンジン``と``JavaScriptエンジン``が実行します。

### Download
サーバからリソースをダウンロードします。

### Parse
HTMLとCSSの構文解析を行い、それぞれの``オブジェクトモデル``を構築します。

オブジェクトモデルは以下の段階を経て作成されます。

1. バイト
2. 文字
3. トークン
4. ノード
5. オブジェクトモデル

レンダリングの結果、Webページを構成する要素が``API(Application Programming Interface)``として利用できるようになります。そしてAPIは、JavaScriptから利用することができます。

オブジェクトモデルは``APIの集合体``です。オブジェクトモデルに変換されることで、JavaScriptコードから操作が可能になります。

#### HTML

HTMLを解析して作られるオブジェクトモデルが``DOM(Document Object Model)``です。最終的にHTMLのタグがツリー構造の集合体になりますが、これを``DOMツリー``と呼びます。

> [ドキュメントオブジェクトモデル (DOM)](https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model)
> [DOM ツリー](https://ja.javascript.info/dom-nodes)

#### CSS

CSSから変換されるオブジェクトモデルは``CSSOM(CSS Object Model)``です。ツリー構造は``CSSOMツリー``と呼ばれます。

> [CSS Object Model](https://developer.mozilla.org/ja/docs/Web/API/CSS_Object_Model)

### Scripting
必要があればJavaScriptを解析し、コードを実行します。

この工程は``JavaScriptエンジン``が担当します。

1. 字句解析 → トークン
2. 構文解析 → 構文木
3. コンパイル → 実行ファイル
4. 実行

### Style (Calculate Style)
DOMツリーとCSSOMツリーを組み合わせます。
マッチングの完成形は``レンダーツリー(Render Tree)``と呼ばれます。

JavaScriptによるDOM操作が行われた時などは、再度実行されます。

### Layout (Reflow)
それぞれの要素の位置と大きさの計算を行い、``レイアウトツリー(Layout Tree)``が構築されます。

JavaScriptによる変更が行われた時などは、再度実行されます。

### Paint
画面へ対する``描写命令(Paint Records)``を作成します。

### Rasterize
ピクセル(画素)を描画したレイヤー(階層構造)を作成します。集合体は``レイヤーツリー(Layer Tree)``と呼ばれます。

レイヤーで分離することにより、内容変更時に再計算による負荷が減ります。

### Composite Layers
レイヤーを合成し、ブラウザに表示する画面を出力します。

## Google Chromeにおける表記
Google Chromeのデベロッパーツールでは、以下の表記でまとめられています。``Performanceタブ``から確認することができます。

> [Chrome DevToolsを使用してサイトのパフォーマンス改善をしてみた](https://tech.willgate.co.jp/entry/2018/09/19/142216)

| 項目       | 工程 |
|:----------|:------------------|
| Loading   | Download, Perse |
| Scripting | Scripting |
| Rendering | Style, Layout |
| Painting  | Paint, Rasterize, Composite Layers |

## 参考リンク
- [オブジェクトモデルの構築](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model?hl=ja)
- [ブラウザはどのようにコンテンツをレンダリングしているのか？
](https://gigazine.net/news/20180323-rendering-engine/)
- [フロントエンジニアなら知っておきたいブラウザレンダリングの仕組みをわかりやすく解説！](https://leap-in.com/ja/lets-learn-how-to-browser-works/)
- [ブラウザレンダリングの仕組みを覚えておきたい 2019.04.15Googleサーバーの理解](https://shu-sait.com/browser-rendering-shikumi/)
- [ブラウザレンダリングを理解するため簡単にまとめてみた](https://qiita.com/mikimhk/items/7cfbd6c94d0f3d7aa51f)

# 仮想DOMについて
2020年1月2日追記。
@hiro_matsuno2 さん、ご指摘ありがとうございました。

``React``や``Vue.js``などのフレームワークでは``仮想DOM(Virtual DOM)``という概念が使われています。
>[仮想DOMと内部処理](https://ja.reactjs.org/docs/faq-internals.html)

こちらの記事で、仮想DOMの概要が分かりやすく説明されています。
>[VirtualDOMの仕事ってなに？(Reactの表示速度がはやい理由)]
(https://qiita.com/risagon/items/019942c60e9c3e6c05a5)

- 最初に仮想DOMを構築し、それを元にリアルDOMを構築する。
- ツリー構造に変化があれば、新しく仮想DOMが構築される。
- その後、旧仮想DOMと新仮想DOMの差分を割り出し、その差分だけリアルDOMが再構築される。

仮想DOMの構築はリアルDOMほど時間がかからないそうです。リアルDOMも一から構築し直す必要がなくなり、それゆえに早いとのこと。

## 参考リンク
- [いまさら聞けないReact、Virtual DOM、JSX超入門 (1/3)](https://www.atmarkit.co.jp/ait/articles/1607/26/news138.html)
- [自作フレームワークをつくって学ぶ 仮想DOM実践入門](https://kuroeveryday.blogspot.com/2018/11/how-to-create-virtual-dom-framework.html)
- [なぜ仮想DOMという概念が俺達の魂を震えさせるのか](https://qiita.com/mizchi/items/4d25bc26def1719d52e6)
- [仮想DOMの内部の動き](https://postd.cc/the-inner-workings-of-virtual-dom/)