架构

本页内容

EmDash 在 Astro 应用内运行。公共页面和管理面板共享 EmDash 运行时、数据库和媒体存储。它们是一个部署应用的组成部分,而非一个前端和一个独立的 CMS 服务。

EmDash 站点的组成部分

下表展示了每个部分如何通过 EmDash 运行时连接:

部分动作连接
管理面板保存条目和媒体将更改发送到 EmDash 运行时
Astro 页面和组件为公共站点查询条目通过 EmDash 运行时读取内容
EmDash 运行时应用内容模型、发布规则、查询、插件和 API 行为读写数据库和媒体存储
SQL 数据库存储内容模型、条目、用户、设置和其他记录由 EmDash 运行时使用
媒体存储存储上传的文件由 EmDash 运行时使用

编辑器使用管理面板处理内容。站点开发者通过编写 Astro 页面和组件决定内容的呈现方式。双方使用相同的内容模型:描述每个条目的集合和字段定义。

数据库存储内容模型、条目、用户、设置和其他 CMS 记录。媒体存储适配器保存上传的文件。条目中的媒体字段引用存储的媒体项,而不是将文件字节放在内容表中。

Astro 的配置

EmDash 站点需要服务器渲染,因为管理面板、API 路由和当前内容在运行时提供。使用 output: "server" 和部署平台的适配器配置 Astro。

在 Astro 集成数组中同时注册 React 和 EmDash。React 负责管理面板的水合;如果安装了 @astrojs/react 但数组中缺少 react(),管理页面将停留在 正在加载 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 实时内容集合:

import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";

export const collections = {
	_emdash: defineLiveCollection({ loader: emdashLoader() }),
};

页面然后调用 getEmDashCollection() 获取列表或 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>

服务器渲染的页面针对传入请求执行此查询,受你配置的缓存约束。预渲染页面在构建期间执行,在下一次构建之前无法显示后续编辑。

模型如何变更

管理员可以在管理面板中创建集合和字段。EmDash 更改数据库模式,使后续条目和查询使用新模型。种子文件提供了一种版本控制的方式来描述另一个环境的起始模型,生成的 TypeScript 声明帮助开发者在代码中使用当前模型。

这些工具描述和更改的是同一个模型;它们不创建并行副本。有关工作流和数据安全边界,请阅读内容模型

插件如何扩展运行时

插件可以响应内容和媒体事件,添加 API 路由、设置或管理界面。原生插件使用宿主应用的访问权限运行。标准格式插件在站点配置沙盒运行器并授予功能时可以在隔离的运行时中运行。在安装或构建之前,请阅读选择插件格式