# 機能設計書 56-ブラウザビルド（@tailwindcss/browser）

## 概要

本ドキュメントは、ブラウザ上でTailwind CSSをリアルタイムにコンパイル・適用する機能 `@tailwindcss/browser` の機能設計を記述する。DOMのclass属性変更をMutationObserverで監視し、動的にユーティリティCSSを生成・注入する。

### 本機能の処理概要

**業務上の目的・背景**：プロトタイピング、ドキュメントサイトのインタラクティブデモ、CodePenなどのオンラインプレイグラウンドにおいて、ビルドツールなしでブラウザ上で直接Tailwind CSSを利用したいという需要がある。`@tailwindcss/browser` は、ブラウザ上でTailwind CSSのコンパイラを実行し、DOMの変更をリアルタイムに検知してユーティリティCSSを生成・注入する機能を提供する。

**機能の利用シーン**：HTMLファイルに `<script src="@tailwindcss/browser">` を追加し、`<style type="text/tailwindcss">` タグでカスタムCSSを記述するだけで、Tailwind CSSが利用可能になる。ビルドプロセスは不要。

**主要な処理内容**：
1. `<style type="text/tailwindcss">` タグの検出と内容収集
2. Tailwind CSSコンパイラの作成（tailwindcss.compile）
3. 仮想スタイルシートの読み込み（loadStylesheet）
4. MutationObserverによるDOM変更の監視（class属性変更、ノード追加、スタイルシート変更）
5. DOM要素からのクラス名収集
6. compiler.build()によるユーティリティCSS生成
7. `<style>` タグへのCSS注入
8. ビルドキューによる非同期ビルドの直列化

**関連システム・外部連携**：tailwindcss コアライブラリ（compile関数）、ブラウザDOM API（MutationObserver、document.querySelectorAll）、Performance API（計測）

**権限による制御**：特になし。ブラウザ上で実行されるクライアントサイドスクリプト。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ブラウザランタイムのため特定の画面に紐づかない |

## 機能種別

リアルタイム処理 / DOM監視 / CSS生成・注入

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| style[type="text/tailwindcss"] | HTMLStyleElement | No | カスタムCSS入力。省略時は `@import "tailwindcss"` がデフォルト挿入される | - |

### 入力データソース

- `<style type="text/tailwindcss">` タグの textContent
- DOM要素のclass属性（document.querySelectorAll('[class]')）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sheet.textContent | string | コンパイル済みユーティリティCSS |

### 出力先

ブラウザDOMの `<style>` タグ（document.head に追加される）

## 処理フロー

### 処理シーケンス

```
1. スクリプト読み込み時の初期化
   └─ sheet (出力用<style>タグ) の作成
2. 初回フルリビルド（rebuild('full')）
   └─ a. createCompiler(): <style type="text/tailwindcss"> の収集
   └─ b. tailwindcss.compile(css): コンパイラ作成
   └─ c. build('full'): DOM全体のクラス収集 → compiler.build()
3. <style>タグのDOM挿入
   └─ document.head.append(sheet)
4. MutationObserver設定
   └─ a. styleObserver: スタイルシート内容変更を監視 → フルリビルド
   └─ b. documentObserver: class属性変更・ノード追加を監視
5. 変更検知時のリビルド
   └─ class変更/ノード追加 → インクリメンタルリビルド
   └─ スタイルシート変更/新スタイルシート追加 → フルリビルド
```

### フローチャート

```mermaid
flowchart TD
    A[スクリプト読み込み] --> B[出力用styleタグ作成]
    B --> C[rebuild full]
    C --> D[createCompiler]
    D --> E[style type=text/tailwindcss を収集]
    E --> F{@import含む?}
    F -->|No| G["@import 'tailwindcss' を先頭に追加"]
    F -->|Yes| H[そのまま使用]
    G --> I[tailwindcss.compile]
    H --> I
    I --> J[build full]
    J --> K[DOM全体からclass収集]
    K --> L[compiler.build]
    L --> M[sheet.textContentにCSS設定]
    M --> N[document.headにsheet追加]
    N --> O[MutationObserver設定]
    O --> P{DOM変更検知}
    P -->|class属性変更| Q[rebuild incremental]
    P -->|ノード追加| R{STYLEタグ?}
    R -->|Yes| S[rebuild full]
    R -->|No| Q
    P -->|スタイルシート内容変更| S
    Q --> T[新規クラスのみ収集]
    T --> U{新規クラスあり?}
    U -->|Yes| L
    U -->|No| V[スキップ]
    S --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-56-01 | デフォルトimport挿入 | CSSに@importが含まれない場合、`@import "tailwindcss"` を先頭に挿入 | createCompiler実行時 |
| BR-56-02 | スタイルタイプ識別 | `type="text/tailwindcss"` のstyleタグのみを入力CSSとして認識 | createCompiler実行時 |
| BR-56-03 | インクリメンタルビルド最適化 | 既知のクラス名はSetで管理し、新規クラスのみをbuildに渡す | build('incremental')時 |
| BR-56-04 | インクリメンタルスキップ | 新規クラスが0件かつインクリメンタルの場合はビルドスキップ | build('incremental')時 |
| BR-56-05 | ビルドキュー直列化 | buildQueueのPromiseチェーンでビルドを直列化し、並行実行を防止 | rebuild呼び出し時 |
| BR-56-06 | 出力styleタグ除外 | 出力用styleタグ自身のノード追加イベントはスキップ（無限ループ防止） | MutationObserver内 |
| BR-56-07 | CSS変更検出の最適化 | lastCss変数で前回のCSS内容を記憶し、内容が変わらなければコンパイラを再作成しない | createCompiler時 |
| BR-56-08 | 仮想スタイルシート | tailwindcss/index.css等はassetsモジュールから仮想パスで提供 | loadStylesheet内 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | インポート未対応 | loadStylesheetで認識されないIDを@importした場合 | Error("The browser build does not support @import for ...") をthrow |
| - | プラグイン未対応 | loadModuleが呼ばれた場合（プラグイン/設定ファイル読み込み） | Error("The browser build does not support plugins or config files.") をthrow |

### リトライ仕様

buildQueueのPromiseチェーン内でエラーがcatchされ、I.error()で記録された後、次のビルドは通常通り実行される。

## トランザクション仕様

該当なし

## パフォーマンス要件

- MutationObserverによる効率的なDOM変更検知（ポーリングではない）
- 既知クラスのSet管理によるインクリメンタルビルド
- Performance API（performance.mark/measure）による計測データの提供
- ビルドキューの直列化によるリソース競合の防止

## セキュリティ考慮事項

- ブラウザ上で実行されるため、CSPの制限を受ける可能性がある（style-src）
- プラグインやコンフィグファイルのロードは意図的に無効化されている

## 備考

- Node.js環境やビルドツールは不要で、scriptタグの読み込みのみで動作する
- @tailwindcss/formsなどのプラグインはブラウザビルドでは使用不可
- カスタムCSSの@importはtailwindcss関連のみサポート
- ブラウザDevToolsのPerformanceタブでビルド計測データを確認可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | モジュールスコープの状態変数（compiler, classes, lastCss, sheet, buildQueue, nextBuildId）を確認（16-44行目） |
| 1-2 | instrumentation.ts | `packages/@tailwindcss-browser/src/instrumentation.ts` | ブラウザ版Instrumentationクラス（Performance API使用） |

**読解のコツ**: モジュールスコープの変数が状態を保持する。compilerはawait後の結果型、classesはSetで既知クラスを管理、buildQueueはPromiseチェーンでビルドを直列化している。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | スクリプト末尾の初期化処理（292-294行目） |

**主要処理フロー**:
1. **292行目**: `rebuild('full')` - 初回フルリビルドの実行
2. **294行目**: `document.head.append(sheet)` - 出力用styleタグのDOM追加
3. **249-290行目**: メインのMutationObserver設定（document.documentElement監視）

#### Step 3: コンパイラ作成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | createCompiler関数（60-107行目）: スタイルシート収集 → compile |
| 3-2 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | loadStylesheet関数（109-171行目）: 仮想スタイルシート解決 |
| 3-3 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | loadModule関数（173-175行目）: プラグイン読み込み拒否 |

#### Step 4: ビルドとリビルドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | build関数（177-206行目）: クラス収集 → compiler.build |
| 4-2 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | rebuild関数（208-230行目）: ビルドキュー管理 |

#### Step 5: MutationObserverを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | styleObserver（233-243行目）: スタイルシート変更監視 |
| 5-2 | index.ts | `packages/@tailwindcss-browser/src/index.ts` | documentObserver（249-290行目）: DOM変更監視 |

### プログラム呼び出し階層図

```
[スクリプト読み込み]
    |
    +-- rebuild('full')
    |       +-- createCompiler()
    |       |       +-- document.querySelectorAll('style[type="text/tailwindcss"]')
    |       |       +-- tailwindcss.compile(css, { loadStylesheet, loadModule })
    |       |               +-- loadStylesheet(id, base)
    |       |               |       +-- assets.css.index / preflight / theme / utilities
    |       |               +-- loadModule() → Error
    |       |
    |       +-- build('full')
    |               +-- document.querySelectorAll('[class]')
    |               +-- compiler.build(newClasses)
    |               +-- sheet.textContent = CSS
    |
    +-- document.head.append(sheet)
    |
    +-- MutationObserver(documentObserver)
    |       +-- [class変更/ノード追加] → rebuild('incremental')
    |       +-- [STYLEタグ追加] → rebuild('full')
    |
    +-- MutationObserver(styleObserver)
            +-- [スタイルシート変更] → rebuild('full')
```

### データフロー図

```
[入力]                          [処理]                          [出力]

<style type=               createCompiler()
"text/tailwindcss">  ───▶  tailwindcss.compile() ───▶  compiler
                                   |
DOM要素の                          v
class属性      ───▶  build() → classList収集  ───▶  新規クラスSet
                                   |
                                   v
                           compiler.build()  ───▶  CSS文字列
                                   |
                                   v
                           sheet.textContent = CSS  ───▶  <style>タグ
                                                          (document.head)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/@tailwindcss-browser/src/index.ts` | ソース | ブラウザビルドのメインエントリーポイント |
| assets.ts | `packages/@tailwindcss-browser/src/assets.ts` | ソース | 仮想スタイルシートのアセット定義 |
| instrumentation.ts | `packages/@tailwindcss-browser/src/instrumentation.ts` | ソース | ブラウザ版パフォーマンス計測（Performance API） |
| types.d.ts | `packages/@tailwindcss-browser/src/types.d.ts` | ソース | 型定義 |
