アーキテクチャ
このページで分かること
- EmDashのサイトを構成する部分(管理画面、Astroのページとコンポーネント、EmDashのランタイム、SQLデータベース、メディアストレージ)と、それぞれのつながり
- Astroで必要な設定(
output: "server"、アダプター、ReactとEmDashのインテグレーション)と、ページがコンテンツを取得する仕組み - コンテンツモデルの変わり方と、プラグインがランタイムを拡張する方法
このページの目次
EmDashは、Astroのアプリケーションの中で動きます。公開ページと管理画面は、EmDashのランタイム、データベース、メディアストレージを共有します。フロントエンドと別のCMSサービスという関係ではなく、1つのデプロイされたアプリケーションの一部です。
EmDashのサイトを構成する部分
次の表は、各部分がEmDashのランタイムを通じてどのようにつながるかを示します。
| 部分 | 役割 | つながり |
|---|---|---|
| 管理画面 | エントリーとメディアを保存する | 変更をEmDashのランタイムに送る |
| Astroのページとコンポーネント | 公開サイト用にエントリーを取得する | EmDashのランタイムを通じてコンテンツを読み込む |
| EmDashのランタイム | コンテンツモデル、公開のルール、取得、プラグイン、APIの動作を適用する | データベースとメディアストレージを読み書きする |
| SQLデータベース | コンテンツモデル、エントリー、ユーザー、設定、そのほかのレコードを保存する | EmDashのランタイムが使う |
| メディアストレージ | アップロードされたファイルを保存する | EmDashのランタイムが使う |
編集者は、管理画面でコンテンツを扱います。サイトの開発者は、Astroのページとコンポーネントを書いて、そのコンテンツの見せ方を決めます。どちらも同じコンテンツモデルを使います。コンテンツモデルとは、各エントリーを表すコレクションとフィールドの定義です。
データベースには、コンテンツモデル、エントリー、ユーザー、設定、そのほかのCMSのレコードが保存されます。アップロードされたファイルは、メディアストレージのアダプターが保持します。エントリーのメディアフィールドは、ファイルのデータそのものをコンテンツのテーブルに入れるのではなく、保存されたメディアの項目を参照します。
やさしい解説
WordPressでは、PHPのテーマと管理画面(wp-admin)が1つのWordPressの中で動き、同じデータベースを使います。EmDashも同じく、公開ページと管理画面が1つのアプリケーションの中にあり、同じデータベースとメディアストレージを使います。違うのは、公開ページを作るのがPHPのテーマではなく、Astroのページとコンポーネントである点です。管理画面で保存した内容も、Astroのページが読み込む内容も、すべて「EmDashのランタイム」を通ります。
Astroで設定すること
管理画面、APIのルート、最新のコンテンツは実行時に配信されるため、EmDashのサイトにはサーバーでの描画(サーバーレンダリング)が必要です。Astroに output: "server" と、デプロイ先のプラットフォーム用のアダプターを設定します。
Astroの integrations の配列に、ReactとEmDashの両方を登録します。Reactは管理画面をハイドレーションします。@astrojs/react をインストールしていても、配列に react() がない場合、管理画面のページは Loading EmDash... のまま止まります。
次のNode.jsの例では、SQLiteのデータベースとローカルのメディアストレージを指定しています。
import node from "@astrojs/node";
import react from "@astrojs/react";
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
output: "server",
adapter: node({ mode: "standalone" }),
integrations: [
react(),
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});
このインテグレーションでは、ほかの対応済みのデータベースやストレージのアダプターも使えます。storage を省略した場合はローカルのストレージのアダプターがデフォルトになりますが、本番環境では、アプリケーションのリリースやインスタンスをまたいで保持されるストレージが必要です。使えるアダプターとオプションは、設定リファレンスを参照してください。
ページがコンテンツを取得する仕組み
src/live.config.ts は、EmDashのローダーをAstroのライブコンテンツコレクション(Live Content Collection)として登録します。
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({ loader: emdashLoader() }),
};
ページは、一覧の取得には getEmDashCollection() を、1件のエントリーの取得には getEmDashEntry() を呼び出します。次のクエリは、ページの描画時に投稿を読み込みます。
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) throw error;
---
<ul>{posts.map((post) => <li>{post.data.title}</li>)}</ul>
サーバーで描画するページは、設定したキャッシュの影響を受けつつ、リクエストが来るたびにこのクエリを実行します。事前に描画するページ(プリレンダリング)はビルド中にクエリを実行するため、次にビルドするまで、あとからの編集は表示されません。
やさしい解説
WordPressのテーマでは、WP_Query などで投稿を取り出してテンプレートに表示します。EmDashでは、Astroのページの中で getEmDashCollection()(一覧)や getEmDashEntry()(1件)を呼び出して、コンテンツを取り出します。サーバーで描画するページは、アクセスがあるたびに取り出すため、管理画面で公開した変更がすぐに表示されます。事前に描画したページは、もう一度ビルドするまで変わりません。
モデルの変わり方
管理者は、管理画面でコレクションとフィールドを作成できます。EmDashはデータベースのスキーマを変更し、以降のエントリーと取得が新しいモデルを使うようにします。シードファイルは、別の環境で使う初期のモデルを、バージョン管理できる形で記述する手段です。生成されるTypeScriptの型宣言は、開発者がコードの中で現在のモデルを使うのに役立ちます。
これらのツールは、同じモデルを記述・変更するもので、並行する別のコピーを作るものではありません。作業の流れと、データを安全に保つための境界については、コンテンツモデルを参照してください。
プラグインによるランタイムの拡張
プラグインは、コンテンツやメディアのイベントに反応したり、APIのルート、設定、管理画面の画面を追加したりできます。ネイティブ型プラグインは、ホストのアプリケーションと同じアクセス権を持って動きます。標準形式のプラグインは、サイトがサンドボックスランナーを設定し、権限(Capability)を付与している場合、隔離されたランタイムで動かせます。プラグインをインストールしたり作ったりする前に、プラグイン形式の選び方を読んでください。