プラグインアーキテクチャ
Crowi 2.0 のプラグインの仕組みと設計思想 (RFC-0001 / RFC-0002)
Crowi 2.0 は、ファイルストレージ・全文検索・レンダラ・認証・通知といった 本来コアと独立した関心事を、独立配布可能な プラグイン として切り出した アーキテクチャを採用しています。設計の経緯は RFC-0001 (プラグインアーキテクチャ) と RFC-0002 (レンダラプラグインアーキテクチャ) を参照してください。
設計の原則
Crowi のプラグインモデルは、次のいくつかの原則の上に成り立っています。
- バッテリー同梱: プラグインを 1 つも追加しなくても、初期状態の Crowi は完結した Wiki として動作します。ローカルファイルストレージ、MongoDB ベースの検索、メール + パスワード認証、アプリ内通知がデフォルトで 有効です。
- npm パッケージとして配布: プラグインは特別な形式ではなく、通常の npm パッケージです。グローバルなプラグインレジストリや curl パイプ式の インストーラはありません。
- plugin-free な api:
@crowi/apiは SDK (@crowi/plugin-api) と コアのみを同梱し、ドライバは一切含みません。プラグインは別の runner プロジェクト (後述) が所有するため、プラグインの追加・削除 はそのプロジェクトの依存と設定を変えるだけで完結し、api のイメージを 焼き直す必要はありません。 - v2.x の間は API 安定:
@crowi/plugin-api@2.xに対して書かれた プラグインは、v2 系のすべてのマイナーバージョンで動作し続けます。
Tip: プラグインの実行はサンドボックス化されていません。プラグインは サーバと同じ Node 権限で動作します。信頼できる発行元のパッケージのみを 導入してください。
プラグインの種類
Crowi のプラグインは、貢献する拡張ポイントによっておおよそ次の種類に 分かれます。1 つのプラグインが複数の拡張ポイントを実装することもできます。
- ストレージ / 検索 / メール — それぞれ「ドライバ」を
crowi.config.jsonのstorage.driver/search.driver/mail.driverで選択します。複数の ドライバプラグインを導入しておき、設定でどれを使うか切り替えられます。 - レンダラ — 本文の記法を足します。ドライバ選択はありません。
- 認証 — 外部アカウントでのサインインを足します。
- 通知 / 連携 — 通知の宛先と、受信 Webhook などの HTTP ルートを足します。
- ベース (設定のみ) — 後続のプラグインに資格情報を共有します。
拡張ポイントの型は プラグイン SDK、配布しているプラグインと ドライバ名の一覧は ファーストパーティプラグイン に あります。
暗黙のデフォルトプラグイン
3 つのドライバは crowi.config.json に列挙しなくても 毎回 読み込ま
れるため、素のインストールではプラグイン設定が一切不要です。
@crowi/plugin-storage-local— ローカルファイルストレージ@crowi/plugin-search-mongo— MongoDB の$regex検索 (デフォルト の検索ドライバ。Elasticsearch / OpenSearch はオプトイン)@crowi/plugin-mail-smtp— SMTP メール
追加のプラグインを列挙して *.driver を切り替えると、これらのデフォルト
の上に選択肢が積み増されます。
CrowiPlugin と PluginContext
プラグインは @crowi/plugin-api の CrowiPlugin 型を満たすオブジェクトを デフォルトエクスポート し、コアの状態には register* に渡される PluginContext からだけ触れます (コアを直接 import しません)。フィールドとメンバーの一覧は プラグイン SDK にあります。
runner プロジェクトと @crowi/runner ライブラリ
「runner」という語が指す 2 つのものを混同しないでください。
- runner プロジェクト は、プラグインを 所有 する小さな api ランタイム
プロジェクトです。
@crowi/apiと選んだ@crowi/plugin-*を依存に持つpackage.json、crowi.config.json、.envからなる通常の npm プロジェクトです。モノレポにはリファレンス実装apps/crowi-runner(パッケージ名@crowi/runner-app、private) が同梱されており、 セルフホストする運用者はこれと等価なものを自前で用意します。 @crowi/runner(-appなし) はpackages/runnerにある内部 ライブラリです。これは 解決エンジン で、crowi.config.jsonを読み、createRequireで列挙されたプラグインを runner プロジェクトのnode_modules/から読み込みます。
プラグイン解決
api パッケージ自身はプラグインを依存に持ちません。プラグインの npm 名を
解決するのは @crowi/runner ライブラリの役割で、api を起動する runner
プロジェクトに対して解決を行います。
crowi.config.jsonを読み、plugins配列に列挙された名前を取得します (暗黙のデフォルトプラグインを先頭に追加します)。createRequire(<projectDir>/package.json)(ここでprojectDirは runner プロジェクト) を使って、その npm 名を runner プロジェクトのnode_modules/から解決します。- 各プラグインの
requiresを BFS で辿り、推移的な依存も読み込みます。 - 結果として、解決済みの
CrowiPluginインスタンス一覧が api の起動 シーケンスに渡されます。
つまり、運用者がプラグインを 1 つ追加するには次の 2 つを行うだけです。
- runner プロジェクトの
package.jsonの依存にプラグインを加える crowi.config.jsonのpluginsにそのパッケージ名を列挙する (必要なら 対応する*.driverも切り替える)
api の再ビルドは伴いません。具体的な手順は プラグインの導入と設定 を参照してください。
起動シーケンスでの位置づけ
プラグインは、設定とモデルの準備が終わった後、レガシーな mailer / slack 初期化の前に起動します。レンダラのコアパイプライン (TOC / wikilink / メンション / コードブロック) は プラグインより先に 登録されるため、 レンダラプラグインはコアの登録の上に追記する形になります。
関連ページ
- 運用者としてプラグインを有効化する → プラグインの導入と設定
- レンダラプラグインの一覧 → レンダラプラグイン
- 独自プラグインの作り方 → プラグイン開発
- アーキテクチャ全体像 → アーキテクチャ
- SDK の型 → プラグイン SDK