演进已部署站点的模式

本页内容

EmDash 将集合、字段和分类法与内容一起存储在数据库中。请使用本指南来更改这个线上内容模型,同时不要把它与代码部署、首次种子初始化或 EmDash 核心迁移混淆。示例使用 Cloudflare D1;同样的区分适用于每一种数据库适配器。

什么会改变什么

站点会经历四种不同的工作流。每一种作用于不同的层:

工作流变更内容方式
内容编辑条目、媒体、设置管理后台或内容 API
代码部署模板、配置、EmDash 版本wrangler deploy — 可能会迁移由 EmDash 管理的数据库表
首次引导(bootstrap)从空白开始的一切迁移 + 种子文件 + 设置向导,首次启动时自动执行
模式演进集合、字段、分类法管理后台,或针对线上站点执行 emdash schema(本页)

种子文件只参与第三行。它的模式和结构只会应用一次,即在设置向导完成之前的第一个请求时。将修改后的种子文件部署到已有的数据库上不会产生任何效果——演进线上站点的模式始终通过管理后台或 API 进行。

在管理后台中更改模式

管理后台是演进已部署站点的主要方式。在管理后台中打开 Content Types,添加、编辑或移除集合和字段。更改会立即生效——内容 API、loader 和编辑界面都在运行时从数据库读取模式。

可用的字段类型、验证规则和小部件选项请参阅集合和字段。

更改模式后,请重新生成模板所使用的 TypeScript 类型。emdash types 命令从运行中的实例读取模式,因此可以直接指向已部署的站点:

npx emdash types --url https://example.com

通过 CLI 更改模式

emdash schema 命令通过 REST API 与运行中的实例通信,因此它们对已部署站点的作用与对本地开发的作用相同。请先用设备流(device flow)认证一次:

npx emdash login --url https://example.com

或者,在管理后台的 Settings → API Tokens 下创建 API 令牌,并通过 --token 或 EMDASH_TOKEN 环境变量传入——这在 CI 中很有用。

然后使用与本地相同的命令来演进模式:

npx emdash schema add-field posts subtitle --type string --label "Subtitle" --url https://example.com
npx emdash schema remove-field posts legacy_field --url https://example.com
npx emdash schema create projects --label Projects --url https://example.com

这些命令可以提交到脚本中,使每个环境都收到相同顺序的更改。这些命令不会自动保证幂等:针对已存在的对象重新运行 create 或 add-field 可能会失败。请用 emdash schema list 或 get 检查目标,记录每个环境完成了哪些步骤,并在遇到第一个错误时停止。

完整命令列表请参阅 CLI 参考。

保持种子文件同步

嵌入在构建中的种子文件决定了全新数据库初始化成什么样:新的预览环境、灾难恢复重建,或同一站点的第二次部署。如果种子仍在描述入门博客,而生产环境已经演变成别的样子,那么每个新环境都会以错误的模型完成引导。

构建会嵌入找到的第一个种子文件:.emdash/seed.json、package.json#emdash.seed 中的路径,或 seed/seed.json。如果都不存在,则嵌入内置的默认种子(入门博客模型),并且 astro dev 会记录一条警告。

演进已部署站点的模式之后,请将线上模型导出回你的仓库。emdash export-seed 读取本地 SQLite 文件。按照创建异地 D1 转储中的说明创建 SQL 文件,将表和行加载到本地数据库,然后导出种子:

sqlite3 prod.db < backup-schema.sql
sqlite3 prod.db < backup-folders.sql
sqlite3 prod.db < backup-data.sql
npx emdash export-seed --database prod.db > .emdash/seed.json

导出的种子包含线上站点的设置、集合、分类法、菜单、重定向、小工具区域和 section。添加 --with-content 可包含条目。请将更新后的 .emdash/seed.json 与依赖新模式的代码一并提交,这样新环境始终会以代码能够理解的模型完成引导。

在预览环境中演练更改

破坏性的模式更改(移除字段、重构集合)最稳妥的做法是针对生产环境的一次性副本进行演练。

  1. 创建一个单独的预览 D1 数据库,并让 Wrangler 将其添加到 preview 环境:

    npx wrangler d1 create emdash-db-preview \
      --binding DB --env preview --update-config

    确认 env.preview.d1_databases 包含新数据库的名称和 UUID。绑定不会从顶层 Wrangler 配置继承。

  2. 按照创建异地 D1 转储中的说明,从生产环境创建 SQL 文件,然后通过预览环境的 DB 绑定按顺序导入它们:

    npx wrangler d1 execute DB --env preview --remote --file=./backup-schema.sql
    npx wrangler d1 execute DB --env preview --remote --file=./backup-folders.sql
    npx wrangler d1 execute DB --env preview --remote --file=./backup-data.sql
    npx wrangler d1 execute DB --env preview --remote --file=./backup-indexes.sql

    预览站点会在首次调用搜索 API 时重建其搜索索引,如该节所述。

  3. 构建项目,将其部署到预览环境,然后针对预览 URL 运行模式更改:

    npm run build
    npx wrangler deploy --env preview
    npx emdash schema remove-field posts legacy_field --url https://preview.example.com
  4. 验证公开页面、管理后台表单、生成的类型,以及所有读取已更改字段的模板。对生产数据库做一次新的备份,然后针对生产环境把相同的命令只运行一次。

从失误中恢复

  • 某个字段被误删了。 该列及其数据已从线上数据库中消失。请从 D1 Time Travel 的时间点备份中恢复,或者重新添加该字段,并从较早的异地 D1 转储中恢复其值。
  • 新环境以错误的模型完成了引导。 嵌入的种子已过时或缺失。请更新 .emdash/seed.json(参阅保持种子文件同步),重新构建,并将部署指向一个空数据库以再次引导。
  • 模式与模板不一致。 部署与模式更改相互独立,因此请有意识地安排它们的顺序:增量式的模式更改(新集合、新的可选字段)先进行,然后再部署使用它们的代码。对于移除操作,请先部署不再使用该字段的代码,然后再移除该字段。