プロトタイプ保守
このスキルを使用すると、既存のプロトタイプを何度も製品イテレーションする際に、変更が容易になります。
目標は製品を再設計することではありません。現在の動作とビジュアル方向性を維持しながら、保守性、ファイル所有権の明確化、検証速度を向上させます。
範囲と引き継ぎ
- このスキルは、既存のプロトタイプにおける継続的な構造的イテレーションと所有権マッピングに使用します。初回の静的分割またはパッケージングには、利用可能であれば
static-prototype-splitterを使用してください。これは必須の依存関係ではありません。 - 小さなコピー、レイアウト、または動作の変更では、ディレクトリ全体の見直しは必要ありません。リクエストに関連する責任範囲のみを分割します。
- 既存のエントリファイル名、フレームワーク、スクリプトモデル、プレビューワークフローは保持します。以下の
app.htmlレイアウトは例であり、名前の変更を要求するものではありません。 - ファイルの置換、設定、依存関係、ネットワークアクセス、ローカルサーバー、保存データに関するユーザーの許可ルールに従います。このスキルはそれらの権限を付与するものではありません。
トリガー条件
以下のような場合にこのスキルをトリガーします。
- プロトタイプの将来の修正速度を向上させたい場合。
- JS をページ、コンポーネント、フィールド、モーダル、ストア、データレイヤーごとに分割したい場合。
- CSS をベース、レイアウト、ページ、コンポーネント、モーダル、フィールドスコープごとに分割したい場合。
- モックデータ、シードデータ、スキーマ、状態/ストアロジックを分離したい場合。
- プロトタイプ保守用の README を作成または更新したい場合。
- 将来のリクエストをファイルにマッピングする CHANGE-MAP を作成または更新したい場合。
- 既存のインタラクティブプロトタイプの最適化を継続したい場合。
- プレビューと分割ファイルを組み合わせて保守しやすい状態を維持したい場合。
- 将来のプロトタイプ変更をどこで行うべきかを説明したい場合。
デフォルトの原則
- ユーザーの言語とプロトタイプの既存の用語に従います。
- 編集前に現在のエントリとアクティブなスクリプト参照を読み込みます。
- ユーザーが再設計を要求しない限り、元のビジュアルデザインとインタラクションの意図を維持します。
- 明示的に要求されない限り、すべてをフレームワークに書き換えないでください。
- 2つの異なる実装を作成しないでください。結合されたプレビューは、共有/分割されたモジュールを読み込むか、それらから生成される必要があります。
- 変更は保守性と要求された製品動作に焦点を当てます。
- 新しいファイルを追加しただけでは分割は完了しません。各分割では、古いファイルの責任範囲も削減し、将来の編集が1つの明白な所有者を持つようにする必要があります。
- 無関係な変更はそのままにし、元の入力ファイルと置き換えられたファイルは保持します。承認された編集はアクティブな実装に焦点を当て、レガシーファイルを削除したり、承認なしに保護されたドキュメントを置き換えたりしないでください。
- 変更後は、可能な場合に構文とメインプレビューのインタラクションを検証します。
推奨構造
プロジェクトに合わせて名前を調整しますが、静的なインタラクティブプロトタイプには以下の構造を推奨します。
prototype/
├── app.html
├── README-prototype.md
├── CHANGE-MAP.md
├── assets/
│ ├── css/
│ │ ├── base.css
│ │ ├── layout.css
│ │ ├── components.css
│ │ ├── modals.css
│ │ ├── fields.css
│ │ └── pages/
│ │ ├── home.css
│ │ ├── editor.css
│ │ └── fill.css
│ └── js/
│ └── app/
│ ├── core.js
│ ├── runtime.js
│ ├── pages/
│ ├── components/
│ ├── fields/
│ ├── modals/
│ ├── data/
│ ├── store/
│ └── utils/
└── pages/
└── ...
プロトタイプのドメインが異なる場合は、同等の名前を使用してください。重要なのは責任範囲の分割です。
小規模なプロトタイプでは、よりフラットな構造でも問題ありません。頻繁に変更されるプロトタイプでは、上記のディレクトリ構造を推奨します。これにより、将来の各リクエストが小さなファイルにマッピングされます。
レイヤーの責任範囲
エントリレイヤー
現在の結合プレビューエントリを維持します。app.html は以下で使用されるサンプル名です。
これには以下を含める必要があります。
- デバイスフレームまたはプレビューシェル(存在する場合)。
- ルートコンテナ。
- CSS リンク。
- 順序付けられたスクリプト参照。
ほとんどのビジネスロジックを含めるべきではありません。
ページレイヤー
ページレンダリングとページ固有のレイアウトにはページファイルを使用します。
- ホーム/リスト/検索/タブ。
- エディター/作成/編集ページ。
- 入力/プレビュー/送信/詳細ページ。
- ログイン/登録/オンボーディングページ。
- 設定/アカウントページ。
ユーザーがページレイアウトやページコピーの変更を要求した場合、ここから始めます。
1つのページファイルに頻繁に編集される複数のサブビューが含まれている場合は、さらに分割します。例:
pages/home/
├── index.js
├── search.js
├── my-forms.js
└── submitted.js
フィールドまたはコンポーネントレイヤー
繰り返し使用されるUIブロックにはフィールド/コンポーネントファイルを使用します。
- フィールドタイプラベル。
- フィールドデフォルト。
- エディターでのフィールドプレビュー。
- 入力ページコントロール。
- アップロード/画像/ファイル/ラジオ/チェックボックス/OCR/日付レンダラー。
ユーザーが1つの要素タイプの変更を要求した場合、アプリ全体を検索する必要はありません。フィールド設定とレンダラーファイルから始めます。
プロトタイプに多くのフォームコントロールや繰り返しカードがある場合は、レジストリを推奨します。
fields/
├── registry.js
├── text.js
├── image.js
├── file.js
├── options.js
└── ocr.js
モーダルレイヤー
モーダルファイルは以下に使用します。
- フィールド設定シート。
- タイプピッカーシート。
- 並べ替えドロワー。
- 確認ダイアログ。
- 要素追加ライブラリシート。
モーダルの状態は可能な限りローカルに保ち、確認アクション後にのみデータをコミットします。
データレイヤー
データとストアの動作を分離します。
data/ は以下に使用します。
- モックテンプレート。
- 業界/カテゴリリスト。
- フィールドタイプ定義。
- デモユーザーと例。
- シードレコードとフィクスチャ。
store/ は以下に使用します。
- ローカルストレージキー。
- フォームの保存/削除/更新。
- 送信レコードの保存/削除/更新。
- データ正規化とマイグレーション。
プロトタイプが非常に小さい場合を除き、ストレージルールをページレンダラーに混在させないでください。
既存のローカルデータが既に存在する可能性がある場合は、そのキーとユーザーの編集内容を保持します。安定したIDによって不足しているシードレコードのみを追加し、シード処理を冪等にします。編集されたレコードを上書きしたり、アイテムを重複させたり、リロード時にローカルストレージをリセットしたりしないでください。スキーママイグレーションは、文書化された復旧パスを持つ、別個の承認された操作として扱います。
CSS レイヤー
CSS はサイズだけでなく所有権で分割します。
base.css: 変数、リセット、タイポグラフィ。layout.css: シェル、デバイスフレーム、ページコンテナ、グリッドプリミティブ。components.css: ボタン、入力、カード、タブ、チップ。modals.css: シート、ドロワー、確認ダイアログ、トースト。fields.css: フィールドコントロールとフォーム要素プレビュー。pages/*.css: ページ固有のレイアウトと例外。
セレクタが複数のページで再利用されている場合は、components または fields に保持します。特定の1つのページに固有の場合は、そのページのCSSに移動します。
変更マップレイヤー
多くの編集ラウンドが予想されるプロトタイプには CHANGE-MAP.md を追加します。
これにより、一般的なユーザーリクエストがファイルに直接マッピングされます。
# 変更マップ
## ページ
- ホームページ: assets/js/app/pages/home/index.js
- テンプレートページ: assets/js/app/pages/templates/index.js
- フォームエディター: assets/js/app/pages/editor/index.js
## フィールド
- 画像アップロードフィールド: assets/js/app/fields/image.js
- ファイルアップロードフィールド: assets/js/app/fields/file.js
- ラジオ/チェックボックスフィールド: assets/js/app/fields/options.js
## モーダル
- フィールド設定モーダル: assets/js/app/modals/field-settings.js
- 並べ替えドロワー: assets/js/app/modals/sort.js
## データ
- テンプレートデータ: assets/js/app/data/templates.js
- 業界カテゴリ: assets/js/app/data/industries.js
## スタイル
- テンプレートページスタイル: assets/css/pages/templates.css
- フィールドスタイル: assets/css/fields.css
CHANGE-MAP は短く保ちます。これは製品ドキュメントではなく、編集のインデックスです。
ランタイムレイヤー
ランタイムファイルは以下に使用します。
- ルーター/レンダーディスパッチ。
- イベント委譲。
- ジェスチャー処理。
- アクションディスパッチ。
- ブートストラップ。
ランタイムが大きくなった場合は、インタラクションタイプごとに分割しますが、1つの明確なエントリポイントを維持します。
保守用 README
要求に応じて、プロトタイプルートに README-prototype.md を追加または更新します。
以下を含めます。
- プレビューエントリの合計。
- ローカルプレビューURLと予約済みポート(ある場合)。
- ページとファイルのマッピング。
- フィールド/コンポーネントとファイルのマッピング。
- モーダルとファイルのマッピング。
- データレイヤーの場所。
- CSS レイヤーの場所。
- CHANGE-MAP の場所。
- 変更後のリフレッシュと検証方法。
- 「アップロード画像フィールドを変更」や「フォーム送信ページを変更」などの一般的な将来変更の例。
簡潔で有用なものにします。これはプロトタイプを保守する人間のためのものであり、長い開発日誌ではありません。
ワークフロー
-
アクティブなエントリファイルを検査します。
rg --files、grep、および対象を絞った読み取りを使用します。- 結合されたプレビューで実際に読み込まれているスクリプトを確認します。
- 既存の分割ファイルがアクティブであると想定しないでください。
-
現在の所有権を特定します。
- ページレンダラー。
- フィールドレンダラー/設定。
- モーダル/ドロワー。
- ストア/データヘルパー。
- ランタイム/イベントハンドラー。
-
慎重に分割します。
- 動作を維持することが重要な場合は、まず機械的な抽出を推奨します。
app.htmlでスクリプトの読み込み順序を明示的に維持します。- ユーザーが動作の変更も要求しない限り、分割中に動作を変更しないようにします。
- モジュールを抽出した後、古いファイルから対応する責任範囲を削除または縮小します。同じページ、コンポーネント、モーダル、データセット、CSS セレクタに対して2つのアクティブな所有者を残さないでください。
- ユーザーが削除を確認しない限り、レガシーの結合ファイルは削除せず、未使用のままにします。
- 既存のクラシックスクリプトまたは ES モジュールモデルを維持します。関数を移動した後、読み込み順序、エクスポート、インラインイベントハンドラーを確認します。
- ビューのマウント/アンマウント責任を明確にします。ビューを離れるときに古いリスナーとタイマーを削除し、繰り返しナビゲーションでアクションが重複しないようにします。
-
データが増大している場合はデータを分割します。
- 大きなモックデータをページレンダラーやストアファイルから移動します。
- シードフィクスチャは決定論的でスキャンしやすい状態に保ちます。
- 可能な場合は、新しいシードデータを既存のローカルデータにマージします。
- データが
data/に移動された場合は、ストア/状態ファイルが重複したアクティブコピーを保持する代わりに、そのデータを消費するようにします。
-
ビジュアル変更が遅くなっている場合は CSS を分割します。
- base/layout/components/pages から始めます。
- ページのみのセレクタはページ CSS に移動します。
- 再利用可能なコントロールは components または fields CSS に移動します。
- セレクタを移動した後、以前のグローバルスタイルシートから重複したアクティブセレクタを削除します。ただし、共有コンポーネントスタイルとして意図的に保持されている場合は除きます。
- カスケード順序とレスポンシブブレークポイントを維持し、CSS の
url(...)、フォント、インポートパスを新しいファイルの場所に相対的に修正します。
-
README と CHANGE-MAP を更新または作成します。
- 最終的なアクティブな構造を文書化します。
- 将来の一般的なリクエストに対してどのファイルを編集すればよいかを明確にします。
- 必要に応じて、ローカルプレビューURL、予約済みポート、キャッシュバスティング手順を含めます。
-
検証します。
- プロトタイプが実際に所有する JavaScript ファイルを、ネストされたページ/コンポーネントファイルも含めて再帰的にチェックします。Python と Node が既に利用可能な場合、この例では
assets/js以下の.js、.mjs、.cjsをチェックします。プロジェクトに合わせてルートを調整してください。これを実行するためだけにランタイムをインストールしないでください。python3 - <<'PY_CHECK' from pathlib import Path import subprocess import sys root = Path("assets/js") files = sorted(p for p in root.rglob("*") if p.is_file() and p.suffix in {".js", ".mjs", ".cjs"} and not {"node_modules", "vendor", ".git"}.intersection(p.parts)) if not files: sys.exit("JavaScript ファイルが見つかりません。チェックルートを確認してください。") failed = False for path in files: failed |= subprocess.run(["node", "--check", str(path)]).returncode != 0 sys.exit(1 if failed else 0) PY_CHECK - フレームワークプロジェクトや異なるモジュールモードの場合は、既存のプロジェクトチェックを使用します。構文チェックに合格してもブラウザでの動作は保証されません。
- 結合されたプレビューを開きます。
- 影響を受ける動作をベースラインと比較します。これには、進む/戻るナビゲーション、編集したビューの再訪問、モーダルの確認/キャンセル、該当する場合はリフレッシュ後の保存状態が含まれます。
- 可能な場合はブラウザコンソールエラーを確認します。
- プロトタイプが実際に所有する JavaScript ファイルを、ネストされたページ/コンポーネントファイルも含めて再帰的にチェックします。Python と Node が既に利用可能な場合、この例では
分割粒度のルール
これらのルールを使用して、分割不足と過分割の両方を回避します。
- ファイルが無関係なリクエストで繰り返し編集される場合は、分割します。
- ページに独立して変更される複数のサブビューが含まれている場合は、サブビューを分割します。
- モックデータがその周囲のロジックよりも多くのスペースを占める場合は、
data/に移動します。 - いくつかのフィールド/コントロールタイプが独立して変更される場合は
fields/を検討します。数だけを満たすために分割しないでください。 - ダイアログやドロワーに個別の状態やメンテナンスのニーズがある場合は
modals/を検討します。 - CSS の変更に大きなグローバルスタイルシートの検索が必要な場合は、ページとコンポーネントで分割します。
- ファイルが安定しており、めったに編集されない場合は、見た目だけのために分割しないでください。
検証ヘルパー
静的プロトタイプには、シンプルで依存関係のない検証を推奨します。
- JS 構文には
node --checkを使用します。 - キャッシュバスティングには、
app.html?t=20261109-153000のように実際の値を使用します。URL にリテラルに記述されたDate.now()は固定文字列です。HTML クエリだけでは個別にキャッシュされた JS/CSS はリフレッシュされないため、必要に応じてブラウザのキャッシュコントロールまたは既存のアセットバージョニング戦略を使用します。 - ユーザーがポートを選択している場合は、ローカルプレビューポートを安定させます。
- 構造リファクタリング後は、ブラウザで変更されたインタラクションを検証します。
- 互換性のある静的ページでは、直接ファイルを開くことも許容されます。フェッチされたフラグメントやブラウザ ES モジュールは通常 HTTP を必要とします。開き方を文書化し、利用可能な場合は既存のプレビューサーバーを再利用します。新しいサーバーを起動する場合は、ユーザーの許可ルールに従います。
応答スタイル
終了時に、ユーザーに以下を伝えます。
- 何が分割または文書化されたか。
- アクティブなエントリファイル。
- 最も重要な新しいファイルパス。
- README-prototype.md または CHANGE-MAP.md が作成または更新されたかどうか。
- どのような検証が完了したか。
- 意図的に残されたレガシーファイルがある場合。
最終的な応答は簡潔で実用的にします。