1. ブラウザを知る──Webサイトを表示するアプリケーション
インターネットを通じてサーバと通信するクライアント
HTML と CSS を描画する レンダリングエンジン
HTML
HTML のソースコードは、いくつかの手順を踏んでデータ構造を変化させながらブラウザによって解析される
code:mermaid
flowchart LR
文字列 --> トークン
トークン --> DOMツリー
HTML を細かく区切ったときに意味のある文字列の最小単位
1. DOCTYPE: 文書がどのバージョンの HTML を使用するのかを表す
<!DOCTYPE html>
2. 開始タグ: 終了タグとともに使用され、ある要素の開始を表す
e.g. <p>
3. 終了タグ: 開始タグとともに使用され、ある要素の終了を表す
e.g. </p>
4. コメント: 文書の結果に影響はしないコメントを表す
5. 文字: タグを含まない純粋な文字
DOM: HTML 文書の構造とコンテンツを表すデータ構造 DOM ツリーは、ノードによって構成される
code:_
interface Node : EventTarget {
const unsigned short ELEMENT_NODE = 1;
...
readonly attribute Node? firstChild;
readonly attribute Node? lastChild;
readonly attribute Node? previousSibling;
readonly attribute Node? nextSibling;
...
};
インタフェースを実装したオブジェクトは、インタフェースで定義されているデータへのアクセスや操作が可能
e.g.
firstChild フィールドが存在するので、DOM ツリーのすべてのノードは firstChild メンバを持つ
appendChild という操作によって、現在のノード配下に新しいノード(子ノード)を追加できる
Node インタフェースを継承しているインタフェースは 2024 年現在以下の 9 つ
それぞれのタグに対応したインタフェースが、この Element インタフェースを継承する形で実装される
e.g. <a>
code:mermaid
flowchart LR
HTMLAnchorElement --> HTMLElement --> Element --> Node
CSS
CSS もいくつかの手順を踏んでデータ構造を変化させながらブラウザによって解析される
code:mermaid
flowchart LR
文字列 --> トークン --> CSSOM
CSS を細かく区切ったときに意味のある文字列の最小単位
ident-token: 変数などの識別子を表す
number-token: 数字を表す
hash-token: ハッシュ記号を表す
delim-token: 区切り文字を表す
colon-token: コロンを表す
semicolon-token: セミコロンを表す
{-token: 始め波括弧を表す
}-token: 終わり波括弧を表す
ブラウザが CSS の種類を解析し、ツリーの形で表現したデータ構造
CSSOM の情報に基づいてツリーの各ノードにスタイルを適用したり、各ノードの大きさや位置を決定する
DOM ツリー同様、ノードによって構成される
違いとしては、DOM ツリーはすべてのノードが Node インタフェースを実装しているが、CSSOM には様々な種類のノードが存在 する
e.g.
1 つの CSS 文書のルートノードを表す
IDL による定義
code:_
interface CSSStyleSheet : StyleSheet {
constructor(optional CSSStyleSheetInit options = {});
readonly attribute CSSRule? ownerRule;
SameObject readonly attribute CSSRuleList cssRules; unsigned long
insertRule(CSSOMString rule, optional unsigned long index = 0);
undefined deleteRule(unsigned long index);
Promise<CSSStyleSheet> replace(USVString text);
undefined replaceSync(USVString text);
};
CSSRuleList cssRules : どのセレクタに対してどのようなスタイルを適用するかを表す CSS ルールのリスト
1 つの CSS ルールのノードを表す
IDL による定義
code:_
interface CSSStyleRule : CSSGroupingRule {
attribute CSSOMString selectorText;
readonly attribute CSSStyleProperties style;
};
CSSOMString selectorText: セレクタ
CSSStyleProperties style: プロパティに対する値
e.g.
CSS
code:css
.class {
background-color: red;
}
p {
color: blue;
}
CSSOM
https://scrapbox.io/files/673342b05c802ecbef1df1af.png
ブラウザ が Web ページを表示するために、HTML と CSS をもとに作成する内部的なデータ構造
名称はブラウザによって異なる
DOM ツリーと CSSOM の情報を元に作成され、以下を決定する
各要素が画面上のどこに配置されるか
各要素の幅や高さ
どの要素が他の要素の子要素・兄弟要素であるか
...
e.g.
HTML + CSS
code:html
<html>
<style>
h1 {
color: red;
}
.foo {
display: none;
}
</style>
<body>
<h1>Hello World</h1>
<p class="foo">This is sample text.</p>
</body>
</html>
レイアウトツリー
https://scrapbox.io/files/673344583c26c0ab21be522d.png
JavaScript を実行する JavaScript エンジン
JavaScript エンジン = JavaScript の解釈と実行を行うソフトウェア
VariableStatement : var VariableDeclarationList ;
JavaScript も HTML や CSS 同様、文字列をトークンに分割し、抽象構文木(AST)と呼ばれる 木構造 を作成することで解釈する code:mermaid
flowchart LR
文字列 --> トークン --> AST
JavaScript を細かく区切ったときに意味のある文字列の最小単位
ノードによって構成されており、CSSOM のように様々な種類のノードが存在する
e.g.
code:_
AdditiveExpression :
MultiplicativeExpression
AdditiveExpression + MultiplicativeExpression
AdditiveExpression - MultiplicativeExpression
code:_
VariableDeclaration :
BindingIdentifier Initializer
BuildingPattern Initializer
BindingIdentifier: 変数の名前を表す
BuildingPattern: const [a, b] = [1, 2]; のようなパターンによる複数の変数を表す
Initializer: 初期化式
DOM API
DOM を操作する API
JavaScript 言語の仕様とは無関係であり、独立して存在する
e.g. JavaScript で特定のタグのノードを取得する
code:js
const nodes = document.getElementByTagName('h1');
code:_
interface Document : Node {
...
HTMLCollection getElementsByTagName(DOMString qualifiedName);
...
};
コアの役割を支えるためのさらなる機能
現在のブラウザでは、上記の 3 つのコアの役割に加え、ユーザが使いやすくなるような機能が多く含まれている
e.g.
ブラウザは、HTML や CSS、JavaScript、画像、動画などのリソースをキャッシュする
リソースが再度リクエストされた際に、キャッシュに保存されている場合はブラウザから提供され、ネットワーク 経由の ダウンロード が省略される これにより、Web サイトの読み込み速度の向上が期待できる
保存されたデータは有効期限を過ぎると削除される
誰でも開発でき、機能を公開することで様々な人にブラウザに追加の機能やカスタマイズを提供できる機能
e.g.
タブのグループ化・ピン留め
ブックマーク
履歴
音声検索・操作
パスワード管理
...
上記の役割や機能は、現代のブラウザでは複数の プロセス 上で動いていることが多い このようなブラウザの設計方法をマルチプロセスアーキテクチャと呼ぶ
仕様などで決まっているわけではないが、ブラウザでは主に 2 種類のプロセスが存在する
ブラウザを開くと、まずブラウザプロセスが起動する
そしてタブを 1 つ開くと、1 つのレンダラプロセスが起動する
つまり、10 個タブを開くと 1 個のブラウザプロセスと約 10 個のレンダラプロセスが存在する
warning.icon <iframe> コンテンツも別のレンダラプロセスで実行できるなど、必ずしもタブとレンダラプロセスは 1 : 1 ではない
なぜこれらのプロセスが分離されているか?
HTML や CSS、JavaScript などのリソースは誰が書いたか分からないため信用できない
そこでプロセスを分離すると、メモリ空間も分離され、重要な情報を扱うブラウザプロセスへのアクセスを防げる
UI スレッド(メインスレッド): ユーザとの インタラクション を扱ったり、画面の描画を行ったりするコアとなるスレッド バックグラウンドスレッド: ネットワークの処理などを行う
warning.icon iOS 上でのブラウザアプリ
「ブラウザはマルチプロセスで動いている」と上述したが、iOS で動くブラウザアプリは例外
radish-miyazaki.icon
また、レンダリングエンジンも Apple が開発している WebKit を使用する必要がある 具体的には WKWebView という API を使用して、HTML や CSS の描画をする必要がある ただし、EU における DMA の施行により、Apple によって iOS で設けられていた制限が緩和された しかし、日本は適用外であるため、日本で使用される iOS のブラウザアプリは引き続き WKWebView を使う必要がある
ブラウザのセキュリティ対策