跳过正文
  1. 文章/

开源后端SonicJS部署指南

 Author
文森的科技小站
目录

SonicJS
#

一个现代的、TypeScript优先的无头CMS,专为Cloudflare边缘平台和Hono.js构建。

📦 快速开始:

npx create-sonicjs@latest my-app

⚠️ 注意: 本仓库用于开发SonicJS核心包。构建应用请使用上述命令创建新项目。


🚀 主要特性
#

核心平台
#

  • 边缘优先:专为Cloudflare Workers设计,全球低延迟
  • 🔧 开发者友好:配置优先,TypeScript优先策略
  • 🤖 AI友好:结构化代码,支持AI辅助开发
  • 🔌 插件系统:无需修改核心即可扩展
  • 📱 现代技术栈:Hono.js、TypeScript、D1数据库、R2存储、HTMX
  • 🚀 高速轻量:针对边缘计算优化

高级内容管理(阶段5)
#

  • 📝 集成TinyMCE的富文本编辑器,支持自定义工具栏
  • 🎛️ 动态字段类型(文本、数字、日期、布尔、选择、媒体)
  • 📚 完整的内容版本控制及恢复功能
  • ⏰ 内容发布/撤销时间调度
  • 🔄 支持基于角色权限的工作流(草稿→审核→发布→归档)
  • 💾 自动保存(每30秒)
  • 👁️ 实时内容预览
  • 📋 内容一键复制与模板支持
  • 🛡️ XSS防护,输入验证和HTML转义

🛠 技术栈
#

核心框架
#

  • Hono.js:超快的Cloudflare Workers Web框架
  • TypeScript:严格类型安全
  • HTMX:增强HTML动态交互

Cloudflare服务
#

  • D1:边缘SQLite数据库
  • R2:媒体对象存储
  • Workers:无服务器计算
  • KV:缓存键值存储
  • Images API:图片优化与转换

开发工具
#

  • Vitest:快速单元测试
  • Playwright:端到端测试
  • Wrangler:本地开发与部署
  • Drizzle ORM:类型安全数据库查询

🏁 快速开始
#

快速部署SonicJS流程
#

# 1.本地创建新项目
npx create-sonicjs@latest my-app

# 2.进入项目目录
cd my-app

# 3.登录cloudflare
npx wrangler login

# 4.创建 D1 数据库(记录下database_id):
npx wrangler d1 create my-sonicjs-db

# 5.创建 R2 存储桶(用于存放上传的图片/文件):
npx wrangler r2 bucket create my-sonicjs-media

# 修改配置文件 (wrangler.toml)
[[d1_databases]]
binding = "DB"
database_name = "my-sonicjs-db" # 你创建的名字
database_id = "xxxx-xxxx-xxxx" # 刚才创建后生成的 ID
[[r2_buckets]]
binding = "MEDIA_BUCKET"
bucket_name = "my-sonicjs-media" # 你创建的桶名字

**# 核心步骤:执行数据库迁移(初始化表结构)**
npm run db:migrate

# 启动开发服务器
npm run dev

# 访问 <http://localhost:8787>

**# 核心步骤:同步到远程数据库D1**
npm run db:migrate -- --remote

# 部署到cloudflare
npm run deploy

备注:如遇到无法新增和保存内容,请执行以下步骤

# 初始化本地数据库
# 这一步会创建本地的 .wrangler 文件夹并生成 SQLite 数据库文件,DB必须是配置文件绑定的数据库名
npx wrangler d1 migrations apply DB --local

# 如果遇到无法新增和保存内容,可以用以下命令手动补全缺失的字段
npx wrangler d1 execute DB --local --command="ALTER TABLE content ADD COLUMN created_by TEXT;"
npx wrangler d1 execute DB --local --command="ALTER TABLE content ADD COLUMN updated_by TEXT;"

# 同步数据库表结构(核心步骤)
npx wrangler d1 migrations apply DB --remote

# 线上环境补齐
npx wrangler d1 execute DB --remote --command="ALTER TABLE content ADD COLUMN created_by TEXT;"
npx wrangler d1 execute DB --remote --command="ALTER TABLE content ADD COLUMN updated_by TEXT;"

# 再部署
npm run deploy

默认包含:

  • SonicJS CMS预配置
  • 数据库迁移准备
  • 示例内容集合
  • 管理界面 /admin
  • 即刻部署至Cloudflare

数据库命令集
#

本地数据库命令 (Local Development)
#

这些命令操作的是你电脑本地 .wrangler 文件夹下的 SQLite 数据库。

命令用途备注
npx wrangler d1 migrations apply DB --local应用迁移将代码中的表结构改动同步到本地数据库。
npx wrangler d1 execute DB --local --command="..."执行 SQL直接运行 SQL 语句,如之前补齐字段的操作。
npx wrangler d1 execute DB --local --file=./seed.sql导入数据运行指定的 SQL 文件来初始化测试数据。
npm run db:reset重置数据库(SonicJS 特有脚本) 通常用于清空并重新初始化本地库。
npx wrangler d1 migrations list DB --local查看状态查看本地有哪些迁移脚本已运行。

远程数据库命令 (Production/Cloudflare)
#

当你准备将网站发布到线上时,需要操作 Cloudflare 云端的 D1 实例。

命令用途备注
npx wrangler d1 create <db-name>创建数据库在 Cloudflare 控制台创建一个新的 D1 实例。
npx wrangler d1 migrations apply DB --remote同步表结构发布必做! 将表结构同步到云端数据库。
npx wrangler d1 execute DB --remote --command="..."远程 SQL直接修改线上数据(慎用)。
npx wrangler d1 export DB --remote --output=db.sql导出数据将线上数据备份到本地。

数据库迁移
#

迁移文件位于 packages/core/migrations/,测试应用通过npm工作区符号链接引用。

# 查询迁移状态(本地)
wrangler d1 migrations list DB --local

# 应用本地迁移
wrangler d1 migrations apply DB --local

# 应用生产迁移
wrangler d1 migrations apply DB --remote

迁移开发建议:

  1. packages/core/migrations/ 新建SQL文件,命名格式如 027_add_user_preferences.sql
  2. 编写幂等SQL(CREATE TABLE IF NOT EXISTS等)
  3. 生成迁移包:npm run generate:migrations
  4. 重新构建核心包:npm run build:core
  5. 应用到测试数据库

📁 项目结构
#

sonicjs-ai/
├── packages/
│   ├── core/              # 主CMS包,发布为 @sonicjs-cms/core
│   │   ├── src/
│   │   │   ├── routes/    # 路由处理(管理、API、认证)
│   │   │   ├── templates/ # HTML模板和组件
│   │   │   ├── middleware/# 认证与中间件
│   │   │   ├── utils/     # 工具函数
│   │   │   └── db/        # 数据库模式与迁移
│   │   └── package.json
│   ├── templates/         # 模板系统包
│   └── scripts/           # 构建脚本
├── my-sonicjs-app/        # 测试应用(git忽略)
├── www/                   # 网站营销页
├── tests/e2e/             # 端到端测试
└── drizzle/               # 数据库迁移管理

注意:

  • 本仓库非应用项目,专注于核心包开发。
  • 应用代码在 packages/core/ 或测试应用中。

🔧 内容管理
#

创建集合
#

通过管理界面或数据库定义动态字段集合。示例SQL:

INSERT INTO collections (id, name, display_name, description, schema) VALUES (
  'blog-posts', 'blog_posts', '博客文章', '文章内容集合',
  '{"type":"object","properties":{"title":{"type":"string","required":true}}}'
);

INSERT INTO content_fields (collection_id, field_name, field_type, field_label, field_options) VALUES
  ('blog-posts', 'title', 'text', '标题', '{"maxLength": 200, "required": true}'),
  ('blog-posts', 'content', 'richtext', '内容', '{"toolbar": "full", "height": 400}'),
  ('blog-posts', 'excerpt', 'text', '摘要', '{"maxLength": 500, "rows": 3}'),
  ('blog-posts', 'featured_image', 'media', '特色图片', '{"accept": "image/*"}'),
  ('blog-posts', 'publish_date', 'date', '发布日期', '{"defaultToday": true}'),
  ('blog-posts', 'is_featured', 'boolean', '精选文章', '{"default": false}');

字段类型
#

  • text:单行文本,支持校验
  • richtext:集成TinyMCE的富文本编辑器
  • number:数字输入,支持范围限制
  • boolean:复选框
  • date:日期选择器
  • select:单选/多选下拉
  • media:文件选择及预览

🌐 API接口
#

内容管理
#

方法路径描述
GET/admin/content/new?collection=id创建新内容表单
GET/admin/content/:id/edit编辑内容表单
POST/admin/content/创建内容(含验证)
PUT/admin/content/:id更新内容(含版本控制)
DELETE/admin/content/:id删除内容

高级功能
#

方法路径描述
POST/admin/content/preview发布前预览内容
POST/admin/content/duplicate复制内容
GET/admin/content/:id/versions获取版本历史
POST/admin/content/:id/restore/:version恢复指定版本
GET/admin/content/:id/version/:version/preview预览历史版本

公共API
#

方法路径描述
GET/api/content获取已发布内容(分页)
GET/api/collections/:collection/content获取指定集合内容
GET/api/collections列出所有集合

🚀 部署
#

环境配置示例
#

# wrangler.toml
name = "my-sonicjs-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "your-database-id"

[[r2_buckets]]
binding = "MEDIA_BUCKET"
bucket_name = "my-app-media"

🧪 测试
#

# 运行单元测试
npm test

# 监听模式运行测试
npm run test:watch

# 端到端测试
npm run test:e2e

# 带UI的端到端测试
npm run test:e2e:ui

🔌 插件开发
#

通过插件扩展SonicJS功能,示例代码:

// src/plugins/my-plugin/index.ts
import { Plugin } from '@sonicjs/core'

export default {
  name: 'my-plugin',
  hooks: {
    'content:beforeCreate': async (content) => {
      // 插件逻辑
      return content
    }
  }
} as Plugin

📖 阅读量: