Color mode

プラグイン作成の詳細

このページは、Riebeckite Plugin を実際に設計・実装するときの詳細ガイドです。

初めて Plugin を作る場合は、先に はじめてのプラグイン作成 を読んでください。

このページでは、その先に必要になる、

  • どの拡張ポイントを使うか
  • Plugin 同士の依存関係
  • Lifecycle
  • Content Pipeline
  • Renderer / Page Type
  • CSS / Browser 処理
  • Cache / Diagnostics
  • Package としての配布

までをまとめて扱います。

各型やフィールドの完全な定義を確認したい場合は Plugin API を参照してください。

このページの構成

1. Plugin にするべき機能

Plugin は Riebeckite に再利用可能な機能を追加する仕組みです。

たとえば、

  • Markdown / HTML の解釈
  • Content Transformation
  • 独自形式の Renderer
  • Browser Behavior
  • Diagnostics
  • HTTP Endpoint
  • SEO
  • 独立ページ

などを実装できます。

一方、すべての拡張を Plugin にするわけではありません。

Diagram source
text
flowchart TD
    Q{"何を追加する?"}
 
    Q -->|"Framework共通のContent Model"| Core["Core"]
    Q -->|"再利用可能な機能"| Plugin["Plugin"]
    Q -->|"HonoX / Viteとの接続"| Integration["Integration"]
    Q -->|"Site固有Route / Layout"| App["Application"]
    Q -->|"見た目だけ"| Theme["Theme"]

特に、

text
見た目だけ
  → Theme
 
Site 固有の Route / Layout
  → Application
 
HonoX / Vite との接続
  → Integration
 
Framework 全体の Content Model
  → Core

です。

「何でも Plugin にする」のではなく、その機能がどの責務に属するかを先に判断してください。

2. 最小の Plugin

Plugin は definePlugin() で定義します。

ts
import { definePlugin } from "@riebeckite/core";
 
export function examplePlugin() {
  return definePlugin({
    name: "example",
  });
}

Site では riebeckite.config.ts の plugins に追加します。

ts
export default defineConfig({
  plugins: [
    examplePlugin(),
  ],
});

これが最小構成です。

3. Options を追加する

Plugin に設定が必要なら Factory の引数として受け取ります。

ts
type ExampleOptions = {
  enabled?: boolean;
};
 
export function examplePlugin(
  options: ExampleOptions = {},
) {
  return definePlugin({
    name: "example",
    options,
  });
}

利用側では、

ts
export default defineConfig({
  plugins: [
    examplePlugin({
      enabled: true,
    }),
  ],
});

のように指定できます。

条件付き Plugin も利用できます。

ts
plugins: [
  condition && myPlugin(),
]

false、null、undefined は Plugin Input の解決時に除外されます。

また、

ts
enabled: false

の Plugin も実行されません。

4. 拡張ポイントを選ぶ

Plugin を実装するときは、必要な最小の拡張ポイントを選びます。

Diagram source
text
flowchart TD
    Q{"何を実装する?"}
 
    Q -->|"Markdown / HTML変換"| Pipeline["remark / rehype"]
    Q -->|"Content処理の特定段階"| Hook["Content Hooks"]
    Q -->|"記事内の特殊表示"| Renderer["renderers"]
    Q -->|"独立ページ"| Page["pageTypes"]
    Q -->|"Graph拡張"| Graph["extendContentGraph"]
    Q -->|"URL規則"| Location["resolveContentLocations"]
    Q -->|"CSS"| Asset["assets"]
    Q -->|"Browser処理"| Client["clientEntries"]
    Q -->|"HTTP"| Endpoint["endpoints"]
    Q -->|"SEO"| SEO["seo"]
    Q -->|"診断"| Diagnostics["addDiagnostics"]

現在の主な Contract は次のとおりです。

領域 API
Identity name, enabled, order, options
Dependency provides, requires, optional
Validation validateOptions
Cache cacheVersion, context.cache
Lifecycle setup, buildStart, buildEnd, dispose
Content Hooks onConfigResolved, onContentLoaded, onPostParsed, onPostProcessed, onManifestCreated
Public Location resolveContentLocations
Pipeline remarkPlugins, rehypePlugins, extendMarkdownPipeline, extendHtmlPipeline
Graph extendContentGraph
Diagnostics addDiagnostics
本文内の描画 renderers
独立ページ pageTypes
Browser assets, clientEntries
HTTP endpoints
SEO seo

すべてを実装する必要はありません。

UI や output の拡張ポイントは複数あり、優劣の順列ではなく選択肢です。Markdown / HTML 変換、renderer、Page Type、body Slot、公開する Hono JSX component、client entry があります。どれを選ぶかは UI の提供方法 を参照してください。

27. 実装前の確認

Plugin を作り始める前に、最後に次の順番で考えると責務を分離しやすくなります。

Diagram source
text
flowchart TD
    Start["追加したい機能"]
    Plugin{"再利用可能な機能?"}
 
    Start --> Plugin
 
    Plugin -->|No| Other{"何を変える?"}
    Plugin -->|Yes| Point{"最小のExtension Pointは?"}
 
    Other -->|"見た目"| Theme["Theme"]
    Other -->|"Site固有"| App["Application"]
    Other -->|"Framework共通Model"| Core["Core"]
    Other -->|"HonoX / Vite接続"| Integration["Integration"]
 
    Point --> Implement["Pluginとして実装"]

Plugin にすると決めた後も、

その機能に本当に必要な Extension Point だけを使用する

ことが重要です。

Filesystem を再走査する前に Manifest や Content Graph が使えないか、独自 Route を追加する前に Page Type が使えないか、Client JavaScript を追加する前に SSR / Build-time だけで完結できないかを確認してください。

これによって Plugin を小さく保ち、Core、Integration、Application との不要な結合を避けられます。

関連資料

History

1 changesCollapseExpand
1 + ---
2 + title: プラグイン作成の詳細
3 + sidebar:
4 + label: プラグイン作成の詳細
5 + ---
6 + # プラグイン作成の詳細
7 +
8 + このページは、Riebeckite Plugin を実際に設計・実装するときの詳細ガイドです。
9 +
10 + 初めて Plugin を作る場合は、先に [はじめてのプラグイン作成](../plugins/writing-a-plugin.ja.md) を読んでください。
11 +
12 + このページでは、その先に必要になる、
13 +
14 + - どの拡張ポイントを使うか
15 + - Plugin 同士の依存関係
16 + - Lifecycle
17 + - Content Pipeline
18 + - Renderer / Page Type
19 + - CSS / Browser 処理
20 + - Cache / Diagnostics
21 + - Package としての配布
22 +
23 + までをまとめて扱います。
24 +
25 + 各型やフィールドの完全な定義を確認したい場合は [Plugin API](../reference/plugin-api.ja.md) を参照してください。
26 +
27 +
28 + ## このページの構成
29 +
30 + - [プラグインの依存関係と Lifecycle](./plugin-system/lifecycle.ja.md)
31 + - [Content パイプラインと拡張ポイント](./plugin-system/pipeline.ja.md)
32 + - [プラグインの配布と検証](./plugin-system/distribution.ja.md)
33 +
34 + ## 1. Plugin にするべき機能
35 +
36 + Plugin は **Riebeckite に再利用可能な機能を追加する仕組み**です。
37 +
38 + たとえば、
39 +
40 + - Markdown / HTML の解釈
41 + - Content Transformation
42 + - 独自形式の Renderer
43 + - Browser Behavior
44 + - Diagnostics
45 + - HTTP Endpoint
46 + - SEO
47 + - 独立ページ
48 +
49 + などを実装できます。
50 +
51 + 一方、すべての拡張を Plugin にするわけではありません。
52 +
53 + ```mermaid id="5h0kzp"
54 + flowchart TD
55 + Q{"何を追加する?"}
56 +
57 + Q -->|"Framework共通のContent Model"| Core["Core"]
58 + Q -->|"再利用可能な機能"| Plugin["Plugin"]
59 + Q -->|"HonoX / Viteとの接続"| Integration["Integration"]
60 + Q -->|"Site固有Route / Layout"| App["Application"]
61 + Q -->|"見た目だけ"| Theme["Theme"]
62 + ```
63 +
64 + 特に、
65 +
66 + ```text id="6pgq3j"
67 + 見た目だけ
68 + → Theme
69 +
70 + Site 固有の Route / Layout
71 + → Application
72 +
73 + HonoX / Vite との接続
74 + → Integration
75 +
76 + Framework 全体の Content Model
77 + → Core
78 + ```
79 +
80 + です。
81 +
82 + 「何でも Plugin にする」のではなく、その機能がどの責務に属するかを先に判断してください。
83 +
84 +
85 + ## 2. 最小の Plugin
86 +
87 + Plugin は `definePlugin()` で定義します。
88 +
89 + ```ts id="sf8rf2"
90 + import { definePlugin } from "@riebeckite/core";
91 +
92 + export function examplePlugin() {
93 + return definePlugin({
94 + name: "example",
95 + });
96 + }
97 + ```
98 +
99 + Site では `riebeckite.config.ts` の `plugins` に追加します。
100 +
101 + ```ts id="32z2wh"
102 + export default defineConfig({
103 + plugins: [
104 + examplePlugin(),
105 + ],
106 + });
107 + ```
108 +
109 + これが最小構成です。
110 +
111 +
112 + ## 3. Options を追加する
113 +
114 + Plugin に設定が必要なら Factory の引数として受け取ります。
115 +
116 + ```ts id="m8h0dc"
117 + type ExampleOptions = {
118 + enabled?: boolean;
119 + };
120 +
121 + export function examplePlugin(
122 + options: ExampleOptions = {},
123 + ) {
124 + return definePlugin({
125 + name: "example",
126 + options,
127 + });
128 + }
129 + ```
130 +
131 + 利用側では、
132 +
133 + ```ts id="xw3gy8"
134 + export default defineConfig({
135 + plugins: [
136 + examplePlugin({
137 + enabled: true,
138 + }),
139 + ],
140 + });
141 + ```
142 +
143 + のように指定できます。
144 +
145 + 条件付き Plugin も利用できます。
146 +
147 + ```ts id="d7esfe"
148 + plugins: [
149 + condition && myPlugin(),
150 + ]
151 + ```
152 +
153 + `false`、`null`、`undefined` は Plugin Input の解決時に除外されます。
154 +
155 + また、
156 +
157 + ```ts id="3ud7ge"
158 + enabled: false
159 + ```
160 +
161 + の Plugin も実行されません。
162 +
163 +
164 + ## 4. 拡張ポイントを選ぶ
165 +
166 + Plugin を実装するときは、必要な最小の拡張ポイントを選びます。
167 +
168 + ```mermaid id="z0g35w"
169 + flowchart TD
170 + Q{"何を実装する?"}
171 +
172 + Q -->|"Markdown / HTML変換"| Pipeline["remark / rehype"]
173 + Q -->|"Content処理の特定段階"| Hook["Content Hooks"]
174 + Q -->|"記事内の特殊表示"| Renderer["renderers"]
175 + Q -->|"独立ページ"| Page["pageTypes"]
176 + Q -->|"Graph拡張"| Graph["extendContentGraph"]
177 + Q -->|"URL規則"| Location["resolveContentLocations"]
178 + Q -->|"CSS"| Asset["assets"]
179 + Q -->|"Browser処理"| Client["clientEntries"]
180 + Q -->|"HTTP"| Endpoint["endpoints"]
181 + Q -->|"SEO"| SEO["seo"]
182 + Q -->|"診断"| Diagnostics["addDiagnostics"]
183 + ```
184 +
185 + 現在の主な Contract は次のとおりです。
186 +
187 + | 領域 | API |
188 + | --- | --- |
189 + | Identity | `name`, `enabled`, `order`, `options` |
190 + | Dependency | `provides`, `requires`, `optional` |
191 + | Validation | `validateOptions` |
192 + | Cache | `cacheVersion`, `context.cache` |
193 + | Lifecycle | `setup`, `buildStart`, `buildEnd`, `dispose` |
194 + | Content Hooks | `onConfigResolved`, `onContentLoaded`, `onPostParsed`, `onPostProcessed`, `onManifestCreated` |
195 + | Public Location | `resolveContentLocations` |
196 + | Pipeline | `remarkPlugins`, `rehypePlugins`, `extendMarkdownPipeline`, `extendHtmlPipeline` |
197 + | Graph | `extendContentGraph` |
198 + | Diagnostics | `addDiagnostics` |
199 + | 本文内の描画 | `renderers` |
200 + | 独立ページ | `pageTypes` |
201 + | Browser | `assets`, `clientEntries` |
202 + | HTTP | `endpoints` |
203 + | SEO | `seo` |
204 +
205 + すべてを実装する必要はありません。
206 +
207 + UI や output の拡張ポイントは複数あり、優劣の順列ではなく選択肢です。Markdown / HTML 変換、renderer、Page Type、body Slot、公開する Hono JSX component、client entry があります。どれを選ぶかは [UI の提供方法](../plugins/writing-a-plugin.ja.md#ui-の提供方法) を参照してください。
208 +
209 +
210 + ## 27. 実装前の確認
211 +
212 + Plugin を作り始める前に、最後に次の順番で考えると責務を分離しやすくなります。
213 +
214 + ```mermaid id="7p5i6d"
215 + flowchart TD
216 + Start["追加したい機能"]
217 + Plugin{"再利用可能な機能?"}
218 +
219 + Start --> Plugin
220 +
221 + Plugin -->|No| Other{"何を変える?"}
222 + Plugin -->|Yes| Point{"最小のExtension Pointは?"}
223 +
224 + Other -->|"見た目"| Theme["Theme"]
225 + Other -->|"Site固有"| App["Application"]
226 + Other -->|"Framework共通Model"| Core["Core"]
227 + Other -->|"HonoX / Vite接続"| Integration["Integration"]
228 +
229 + Point --> Implement["Pluginとして実装"]
230 + ```
231 +
232 + Plugin にすると決めた後も、
233 +
234 + **その機能に本当に必要な Extension Point だけを使用する**
235 +
236 + ことが重要です。
237 +
238 + Filesystem を再走査する前に Manifest や Content Graph が使えないか、独自 Route を追加する前に Page Type が使えないか、Client JavaScript を追加する前に SSR / Build-time だけで完結できないかを確認してください。
239 +
240 + これによって Plugin を小さく保ち、Core、Integration、Application との不要な結合を避けられます。
241 +
242 +
243 + ## 関連資料
244 +
245 + - [はじめてのプラグイン作成](../plugins/writing-a-plugin.ja.md) — 最初の Plugin を作る
246 + - [Plugin System](./plugin-system.ja.md) — Plugin System 全体の考え方
247 + - [Plugin API](../reference/plugin-api.ja.md) — API Contract
248 + - [Page System](./page-system.ja.md) — 独立ページ
249 + - [Content System](./content-system.ja.md) — Manifest / Graph / Pipeline
250 + - [Architecture](./architecture.ja.md) — Core / Plugin / Integration / Theme / App の責務
251 + - [Framework Reference](../reference/README.ja.md) — Public API
252 +