mcpField
U
understanding-streamlit-architecture

understanding-streamlit-architecture

github.com/streamlit開発46.2k120 回インストール今日更新
リポジトリ

understanding-streamlit-architecture について

Streamlit のアーキテクチャを把握し、実装箇所を探すための開発者向けドキュメントスキルです。Python バックエンド、React フロントエンド、通信プロトコルを扱います。

主な機能

  1. 01バックエンドとフロントエンドの構成整理
  2. 02WebSocket と Protobuf 通信の解説
  3. 03再実行とセッション状態の説明
  4. 04機能実装のための案内

活用シーン

  1. 01Streamlit の実行モデルの把握
  2. 02UI 要素の前後の実装箇所の特定
  3. 03Streamlit の機能開発

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/streamlit/streamlit --skill understanding-streamlit-architecture

インストール後、Claude Code で/understanding-streamlit-architectureを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
backend.md
communication.md
element-identity.md
frontend.md
layout.md

詳細

Streamlit のアーキテクチャを理解する

Streamlit は、Protocol Buffers を使用した双方向 WebSocket 通信を行うクライアントサーバーアプリケーションです。 このファイルは、簡易的なメンタルモデルとナビゲーションインデックスとして使用してください。実装の詳細については、references/backend.md、references/frontend.md、references/communication.md を参照してください。

概念の用語集

概念説明主要ファイル
コマンドStreamlit の公開 API(st.* 名前空間)で公開されているあらゆる関数です。コマンドは要素/ウィジェットを作成したり、実行フローを制御したり、アプリの動作を設定したりできます。lib/streamlit/delta_generator.py、lib/streamlit/elements/、lib/streamlit/commands/
要素Streamlit のすべての UI コンポーネントを総称する用語です。ウィジェット、コンテナ、表示要素を含みます。Element.proto では約 50 以上の型の oneof ユニオンとして表現されます。proto/streamlit/proto/Element.proto、lib/streamlit/elements/
ウィジェットユーザーの操作によって通常は再実行をトリガーするインタラクティブな要素(button、slider、text_input)です。値は戻り値または st.session_state を介してアクセスできます。on_change="ignore" をサポートするウィジェットは、他の何かが再実行するまで再実行せずにブラウザー内で更新されます。一部の要素は条件付きでウィジェットになります(例: on_select を指定した dataframe/chart)。lib/streamlit/elements/widgets/、frontend/lib/src/components/widgets/
表示要素それ自体では再実行をトリガーせずにコンテンツをレンダリングする非インタラクティブな要素(text、markdown、image、chart)です。lib/streamlit/elements/、frontend/lib/src/components/elements/
コンテナ要素を空間的にグループ化するレイアウトブロックです(sidebar、columns、expander、tabs、form)。要素ツリーでは BlockNode として表現されます。lib/streamlit/elements/layouts.py、Block.proto
DeltaGeneratorst オブジェクトです。UI デルタをキューに追加する API のエントリーポイントです。mixin パターンを使用してすべての st.* コマンドを構成します。lib/streamlit/delta_generator.py
セッションステート再実行をまたいでデータを永続化するセッションごとの辞書(st.session_state)です。ウィジェットの値とユーザー変数を保存します。lib/streamlit/runtime/state/session_state.py
再実行現在のページに対してユーザースクリプトを再実行することです。ウィジェットの操作、st.rerun()、ファイルの変更、またはフラグメントのタイマーによってトリガーされます。セッションステートを保持したまま要素ツリーを再構築します。lib/streamlit/runtime/scriptrunner/script_runner.py、lib/streamlit/commands/execution_control.py
フォームウィジェットの入力をバッチ処理し、フォームの送信まで再実行を遅延させるコンテナ(st.form)です。lib/streamlit/elements/form.py、WidgetStateManager.ts
フラグメントスクリプト全体を再実行せずに、特定の UI セクションの部分的な再実行を可能にするデコレーター(@st.fragment)です。lib/streamlit/runtime/fragment.py
キャッシュ冗長な計算を避けるために関数の結果をメモ化するデコレーター(@st.cache_data、@st.cache_resource)です。lib/streamlit/runtime/caching/
ページst.navigation() と st.Page() を使用するか、pages/ ディレクトリからの自動検出を使用するマルチページアプリシステムです。lib/streamlit/navigation/、lib/streamlit/runtime/pages_manager.py
設定サーバー、クライアント、テーマの設定を制御する .streamlit/config.toml によるアプリ設定です。lib/streamlit/config.py、lib/streamlit/config_option.py
テーマ設定設定またはテーマエディターで定義されるカスタマイズ可能な UI テーマ(Light/Dark/Custom)です。lib/streamlit/runtime/theme_util.py、frontend/lib/src/theme/
シークレット.streamlit/secrets.toml(ローカル)またはプラットフォーム設定(デプロイ済み)による安全な認証情報の保存です。st.secrets を介してアクセスします。lib/streamlit/runtime/secrets.py
接続キャッシュとシークレットの統合を組み込んだデータベース/サービスの抽象化(st.connection)です。lib/streamlit/connections/
カスタムコンポーネントReact/iframe を使用したユーザー構築の拡張機能です。v1(レガシー): declare_component() API。v2(現行): 状態管理が改善された双方向コンポーネント。frontend/component-lib/、frontend/component-v2-lib/、lib/streamlit/components/v1/、lib/streamlit/components/v2/
静的ファイルの配信static/ ディレクトリ内のファイルは、/app/static/* を介して直接配信されます(静的配信が有効な場合)。lib/streamlit/web/server/server.py、lib/streamlit/web/server/starlette/starlette_routes.py
アプリのテストユーザーの操作をシミュレートし、レンダリングされた出力を検査するためのテストフレームワーク(AppTest)です。lib/streamlit/testing/

コアとなるメンタルモデル

flowchart TB
    subgraph Backend["Backend (Python)"]
        Script[User Script]
        DG[DeltaGenerator]
        Runtime[Runtime/AppSession]
    end

    subgraph Protocol["WebSocket + Protobuf"]
        FM[ForwardMsg]
        BM[BackMsg]
    end

    subgraph Frontend["Frontend (React)"]
        App[App.tsx]
        Tree[AppRoot Tree]
        Renderer[ElementNodeRenderer]
        WSM[WidgetStateManager]
    end

    Script --> DG
    DG --> FM
    FM --> App
    App --> Tree
    Tree --> Renderer
    Renderer --> WSM
    WSM -->|User interaction| BM
    BM --> Runtime
    Runtime -->|Rerun| Script

重要な洞察: スクリプトの実行は再実行駆動です。ほとんどのウィジェット操作が再実行(アプリ全体またはフラグメントスコープ)をトリガーします。状態は st.session_state とキャッシュデコレーターによって永続化されます。

実行モデル

Streamlit の実行モデルは従来の Web フレームワークとは異なります。

再実行のトリガー:

  1. ウィジェット操作: ユーザーがボタンをクリックする、スライダーを動かすなど(on_change="ignore" を指定したウィジェットは再実行なしで更新されます)
  2. ソースコードの変更: ファイルウォッチャーがスクリプトの変更を検知
  3. st.rerun(): 明示的なプログラムによる再実行
  4. フラグメントタイマー: @st.fragment(run_every=...) による定期的な再実行

実行順序のニュアンス:

  • スクリプトは再実行のたびに上から下へ実行されます
  • コールバックが最初: on_change/on_click ハンドラーはメインのスクリプト本体の前に実行されます
  • フラグメントは通常、再実行を分離します: @st.fragment 内のウィジェット操作は通常、そのフラグメントのみを再実行します
  • キー付きフラグメントの再実行: ウィジェットのコールバックから st.rerun("<key>") を呼び出すと、指定された @st.fragment(key=...) フラグメントのみが再実行されます
  • 制御フローの例外: st.stop()、st.rerun()、st.switch_page() は実行を停止またはリダイレクトするために例外を発生させます

セッションの分離:

  • 各ブラウザータブ = それぞれ独自の SessionState を持つ別個の AppSession
  • ページを更新すると新しいセッションが作成されます(TTL 内に再接続した場合を除く)
  • セッション間で状態は共有されません(マルチユーザー状態には外部ストレージを使用してください)

再実行をまたいで永続化されるもの(セッション内):

  • st.session_state の値
  • キャッシュされた関数の結果(@st.cache_data、@st.cache_resource)
  • アップロードされたファイル
  • フラグメントの登録

再実行のたびにリセットされるもの:

  • スクリプト内のローカル変数
  • ウィジェットの戻り値(SessionState から再読み取りされます)
  • 要素ツリー(ゼロから再構築され、その後差分が適用されます)

アーキテクチャのレイヤー

バックエンド(Python)
コンポーネントファイル目的
Runtimelib/streamlit/runtime/runtime.pyアプリのライフサイクルとセッションを管理するシングルトン
AppSessionlib/streamlit/runtime/app_session.pyブラウザータブごと: ScriptRunner + SessionState + ForwardMsgQueue
ScriptRunnerlib/streamlit/runtime/scriptrunner/script_runner.py別スレッドでユーザースクリプトを実行
DeltaGeneratorlib/streamlit/delta_generator.pymixin パターンを使用した API のエントリーポイント
SessionStatelib/streamlit/runtime/state/session_state.pyウィジェットの値とユーザー変数
Elementslib/streamlit/elements/st.* コマンドのバックエンド実装

バックエンドの詳細: references/backend.md を参照してください

フロントエンド(TypeScript/React)
コンポーネントファイル目的
Appfrontend/app/src/App.tsx中心となるオーケストレーター
AppRootfrontend/lib/src/render-tree/AppRoot.ts4 つのコンテナーを持つイミュータブルな要素ツリー
ElementNodeRendererfrontend/lib/src/components/core/Block/ElementNodeRenderer.tsxプロトを React コンポーネントにマッピング
WidgetStateManagerfrontend/lib/src/WidgetStateManager.tsウィジェットの状態、フォーム、クエリパラメーター
ConnectionManagerfrontend/connection/src/ConnectionManager.tsWebSocket のステートマシン

フロントエンドの詳細: references/frontend.md を参照してください

通信(Protobuf)
Proto目的
ForwardMsg.protoサーバーからクライアントへ: デルタ、セッションイベント、ナビゲーション
BackMsg.protoクライアントからサーバーへ: ウィジェット状態を伴う再実行リクエスト
Element.protooneof type ユニオン内の約 50 以上の要素タイプ
WidgetStates.protoウィジェットの値: trigger_value、string_value、bool_value など

場所: proto/streamlit/proto/

プロトコルの詳細: references/communication.md を参照してください

必須コンセプト (クイックマップ)

  • レイアウトシステム: 要素の幅/高さパラメータ、flexbox コンテナ、レスポンシブサイジング。
  • スクリプト再実行モデル: ウィジェット操作 -> BackMsg (ClientState) -> バックエンドが SessionState を更新 -> スクリプト再実行 -> ForwardMsg デルタ。
    • 詳細: references/communication.md#widget-interaction-to-script-rerun
  • デルタパスシステム: 要素はデルタパス (例えば [0, 2, 3]) でアドレス指定され、効率的なツリー更新をサポートします。
    • 詳細: references/communication.md#delta-ui-changes
  • active_script_hash のセマンティクス: ForwardMsg.metadata.active_script_hash は、マルチページおよびフラグメントの再実行にわたるノードの所有権をスコープします。
    • 詳細: references/communication.md#forwardmsg-metadata-active_script_hash
  • 要素ツリー構造: フロントエンドの AppRoot は main、sidebar、event、bottom コンテナを BlockNode/ElementNode で維持します。
    • 詳細: references/frontend.md#element-tree-frontendlibsrcrender-tree
  • 要素アイデンティティのセマンティクス: デルタパスはノードがどこに存在するかを決定し、要素 ID は再マウント後にステートフルな要素が以前の状態に再接続できるかどうかを決定します。
    • 詳細: references/element-identity.md
  • フラグメント (@st.fragment): フラグメントの操作は通常、フラグメントスコープの再実行をトリガーし、影響を受ける領域のみを更新します。ウィジェットコールバックは、フラグメントが @st.fragment(key=...) で宣言されている場合、st.rerun("<key>") で名前付きフラグメントをターゲットにすることもできます。

要素アイデンティティ

  • デルタパスは、ノードがレンダーツリーのどこに配置されるかを制御します。
  • 要素 IDは、再マウント後にステートフルな要素が以前の状態に再接続できるかどうかを制御します。
  • ウィジェットは、ID を使用してフロントエンドの WidgetStateManager 状態、BackMsg.WidgetStates、バックエンドの SessionState、コールバック、および st.session_state を接続します。
  • 一部の非ウィジェットも、フロントエンドのみの再構築 (例えばチャートビュー状態やメディア自動再生ガード) に ID を使用します。
  • デルタパスの変更は要素を再マウントする可能性がありますが、安定した element.id により、React は同じレンダリング済み親リストの下に残っているリーフを保持できます。

詳細: references/element-identity.md

主要な実装パターン

  • バックエンド mixin コンポジション: DeltaGenerator は mixin を介して st.* API を構成します。
    • 詳細: references/backend.md#deltagenerator-libstreamlitdelta_generatorpy
  • フロントエンドビジターパターン: レンダーツリーの更新/陳腐化クリーンアップはビジターを使用します。
    • 詳細: references/frontend.md#visitor-pattern
  • メッセージ重複排除: ForwardMsg.hash + ref_hash とフロントエンドの ForwardMsgCache により帯域幅を削減します。
    • 詳細: references/communication.md#message-caching

クイックリファレンス: 機能の追加

  1. Proto 定義: proto/streamlit/proto/<Element>.proto
  2. Element.proto に登録: oneof type に追加
  3. バックエンド mixin: lib/streamlit/elements/<element>.py
  4. フロントエンドコンポーネント: frontend/lib/src/components/elements/<Element>/ または frontend/lib/src/components/widgets/<Element>/ (要素かウィジェットかに応じて)
  5. ElementNodeRenderer に登録: switch 文にケースを追加
  6. Proto をコンパイル: make protobuf

詳細な実装ガイドについては wiki/new-feature-guide.md を参照してください。

このドキュメントのメンテナンス

ここに記載されているコンセプト (Runtime、AppSession、DeltaGenerator、要素ツリー、通信プロトコル、要素アイデンティティなど) のいずれかに影響する変更を行う場合は、このスキルのファイル (SKILL.md、references/backend.md、references/frontend.md、references/communication.md、references/element-identity.md) の関連セクションを更新して、正確さを保ってください。

コメント