資料庫選項

本頁內容

EmDash 支援多種資料庫後端。根據你的部署目標進行選擇。

概覽

資料庫適用場景部署方式
D1Cloudflare Workers邊緣,全球分佈
HyperdriveCloudflare Workers 上的 PostgreSQL邊緣,現有 Postgres
PostgreSQLNode.js 正式環境任何支援 Postgres 的平台
libSQL遠端資料庫邊緣或 Node.js
SQLiteNode.js,本機開發單一伺服器

Cloudflare D1

D1 是 Cloudflare 的無伺服器 SQLite 資料庫。在部署到 Cloudflare Workers 時使用。

import { d1 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: d1({ binding: "DB" }),
		}),
	],
});

設定

選項型別預設值描述
bindingstringwrangler.jsonc 中的 D1 繫結名稱
sessionstring"disabled"讀取副本模式(見下文)
bookmarkCookiestring"__em_d1_bookmark"工作階段書籤的 Cookie 名稱

設置

wrangler.jsonc

{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "emdash-db"
    }
  ]
}

wrangler.toml

[[d1_databases]]
binding = "DB"
database_name = "emdash-db"

讀取副本

D1 支援讀取複寫以降低全球分佈站點的讀取延遲。啟用後,讀取查詢會路由到附近的副本,而不是始終查詢主資料庫。

EmDash 使用 D1 Sessions API 透明地管理此功能。使用 session 選項啟用:

import { d1 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: d1({
				binding: "DB",
				session: "auto",
			}),
		}),
	],
});

工作階段模式

模式行為
"disabled"無工作階段。所有查詢都發送到主資料庫。預設值。
"auto"匿名請求從最近的副本讀取。已認證使用者透過書籤 Cookie 取得 read-your-writes 一致性。
"primary-first""auto" 相同,但第一個查詢始終發送到主資料庫。適用於寫入非常頻繁的站點。

運作方式

  • 匿名訪客取得 first-unconstrained — 讀取從最近的副本取得以實現最低延遲。由於匿名使用者從不寫入,因此不需要一致性保證。
  • 已認證使用者(編輯者、作者)取得基於書籤的工作階段。寫入後,書籤 Cookie 確保下一個請求至少看到該狀態。
  • 寫入請求POSTPUTDELETE)始終從主資料庫開始。
  • 建置時查詢(Astro 內容集合)完全繞過工作階段,直接使用主資料庫。

libSQL

libSQL 是 SQLite 的一個分支,支援遠端連線。當你需要遠端資料庫但不使用 Cloudflare D1 時使用。

import { libsql } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: libsql({
				url: process.env.LIBSQL_DATABASE_URL,
				authToken: process.env.LIBSQL_AUTH_TOKEN,
			}),
		}),
	],
});

設定

選項型別描述
urlstring資料庫 URL(libsql://...file:...
authTokenstring遠端資料庫的認證權杖(本機可選)

本機開發

開發時使用本機 libSQL 檔案:

database: libsql({ url: "file:./data.db" });

PostgreSQL

PostgreSQL 支援需要完整關聯式資料庫的 Node.js 部署。

import { postgres } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: postgres({
				connectionString: process.env.DATABASE_URL,
			}),
		}),
	],
});

設定

你可以使用連線字串或個別參數進行連線:

// 連線字串
database: postgres({
	connectionString: "postgres://user:password@localhost:5432/emdash",
});

// 個別參數
database: postgres({
	host: "localhost",
	port: 5432,
	database: "emdash",
	user: "emdash",
	password: process.env.DB_PASSWORD,
	ssl: true,
});
選項型別描述
connectionStringstringPostgreSQL 連線 URL
hoststring資料庫主機
portnumber資料庫連接埠
databasestring資料庫名稱
userstring資料庫使用者
passwordstring資料庫密碼
sslboolean啟用 SSL
pool.minnumber連線池最小連線數(預設 0)
pool.maxnumber連線池最大連線數(預設 10)

連線池

配接器內部使用 pg.Pool。根據你的部署調整池大小:

database: postgres({
	connectionString: process.env.DATABASE_URL,
	pool: { min: 2, max: 20 },
});

Hyperdrive

使用 hyperdrive() 配接器在 Cloudflare Workers 上執行 EmDash,連接現有的 PostgreSQL — 或 Postgres 相容(如 PlanetScale Postgres)— 資料庫。Hyperdrive 透過 Cloudflare 網路池化和加速連線;EmDash 的 PostgreSQL 方言執行查詢。

import { hyperdrive, r2 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			database: hyperdrive({ binding: "HYPERDRIVE" }),
			storage: r2({ binding: "MEDIA" }),
		}),
	],
});

要求

  • 站點中安裝 pg >= 8.16.3pnpm add pg
  • compatibility_flags: ["nodejs_compat"]
  • compatibility_date >= "2024-09-23"

設置

建立 Hyperdrive 設定並將繫結新增到你的 Wrangler 設定:

wrangler hyperdrive create emdash-db \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full" \
  --caching-disabled

wrangler.jsonc

{
  "hyperdrive": [
    {
      "binding": "HYPERDRIVE",
      "id": "<your-hyperdrive-id>"
    }
  ]
}

wrangler.toml

[[hyperdrive]]
binding = "HYPERDRIVE"
id = "<your-hyperdrive-id>"

設定

選項型別預設值描述
bindingstring"HYPERDRIVE"主(快取停用)Hyperdrive 繫結
cachedBindingstring用於匿名讀取的可選快取啟用繫結
maxnumber5Worker 內到 Hyperdrive 的連線池最大大小

從快取提供匿名讀取

預設情況下,你完全停用 Hyperdrive 快取,因為管理後台和寫入需要 read-after-write 一致性。但匿名公開讀取 — 無工作階段、無寫入 — 可以容忍短暫的過時資料視窗。如果這個權衡可以接受,執行同一資料庫上的兩個 Hyperdrive 設定:一個停用快取(主 binding),一個啟用快取(cachedBinding)。EmDash 將匿名讀取請求透過快取啟用的繫結路由,而所有已認證請求和寫入保持在無快取的主繫結上,保持 read-after-write 一致性。

# 主 — 快取停用(管理、認證請求、寫入、遷移)
wrangler hyperdrive create emdash-db \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full" \
  --caching-disabled

# 快取啟用 — 相同連線字串,快取啟用(僅匿名讀取)
wrangler hyperdrive create emdash-db-cached \
  --connection-string "postgres://user:password@host/db?sslmode=verify-full"
{
	"hyperdrive": [
		{ "binding": "HYPERDRIVE", "id": "<caching-disabled-id>" },
		{ "binding": "HYPERDRIVE_CACHED", "id": "<caching-enabled-id>" }
	]
}
database: hyperdrive({ binding: "HYPERDRIVE", cachedBinding: "HYPERDRIVE_CACHED" });

這是 Cloudflare 為快取文件化的雙設定模式。EmDash 按請求決定使用哪個繫結:

  • 公開站點路徑的匿名讀取GET/HEAD、無工作階段、不在 /_emdash 下)→ 快取啟用的 cachedBinding
  • 已認證請求(編輯者、作者)→ 無快取 binding
  • 寫入POSTPUTDELETE,包括匿名)→ 無快取 binding
  • /_emdash 下的任何請求(管理、設定、認證、內部 API),即使是匿名 GET → 無快取 binding
  • 遷移和冷啟動 → 始終主 binding

SQLite

使用 better-sqlite3 的 SQLite 是 Node.js 部署最簡單的選項。

import { sqlite } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
		}),
	],
});

設定

選項型別描述
urlstringfile: 前綴的檔案路徑

檔案路徑

url 必須以 file: 開頭:

// 相對路徑
database: sqlite({ url: "file:./data/emdash.db" });

// 絕對路徑
database: sqlite({ url: "file:/var/data/emdash.db" });

// 從環境變數
database: sqlite({ url: `file:${process.env.DATABASE_PATH}` });

遷移

EmDash 在每個支援的方言(D1、SQLite、libSQL、PostgreSQL)的第一次請求時自動執行遷移。遷移打包在 emdash 套件中並嵌入到你的建置中。

如果資料庫為空(沒有集合)且設定精靈未完成,EmDash 還會在首次啟動時套用種子檔案。種子從 .emdash/seed.jsonpackage.json#emdash.seed 中的路徑或 seed/seed.json 讀取 — 取最先找到的 — 並在編譯時嵌入建置。如果都不存在,則使用內建的預設種子。後續針對現有資料庫的啟動不會更改其內容。

基於環境的設定

按環境使用不同的資料庫:

import { sqlite, libsql, postgres } from "emdash/db";
import { d1 } from "@emdash-cms/cloudflare";

const database = import.meta.env.PROD ? d1({ binding: "DB" }) : sqlite({ url: "file:./data.db" });

export default defineConfig({
	integrations: [emdash({ database })],
});

選擇也可以基於環境變數而非建置模式:

const database = process.env.DATABASE_URL
	? postgres({ connectionString: process.env.DATABASE_URL })
	: sqlite({ url: "file:./data.db" });