首页
/ Strapi 空白应用示例精讲:从零启动、构建与部署一个最小可用的 Headless CMS

Strapi 空白应用示例精讲:从零启动、构建与部署一个最小可用的 Headless CMS

2026-09-06 12:29:37作者:范靓好Udolf

本文以 Strapi 仓库中 examples/empty 目录下的空白应用模板(empty example)为主体,完整讲解官方 Getting started with Strapi 入门指南所覆盖的 developstartbuilddeploy 四类命令的实际用法与底层实现,并逐一解读该模板的配置文件、入口文件与 TypeScript 编译规则,帮助读者在不依赖任何脚手架预设的情况下,掌握从零启动、定制并部署一个最小可用 Strapi 项目的完整能力。

一、empty 模板是什么:最小化应用骨架

examples/empty 是 Strapi 官方维护的一个"空白起步"应用示例,它的 package.json 中自述为 "description": "A Strapi application"private: true 表明它面向本地开发而非发布。与 examples/complexexamples/getstarted 等携带大量内容类型的示例不同,empty 模板刻意将 src/api/ 目录留空,只保留让一个 Strapi 项目跑起来所必需的最小结构:

examples/empty/
├── config/            # 应用配置(admin、api、database、features、middlewares、plugins、server)
├── database/          # 数据库迁移目录
├── public/uploads/    # 本地上传文件目录
├── src/
│   ├── admin/         # 管理面板前端入口(app.tsx)
│   ├── api/           # 内容类型目录(模板中为空)
│   ├── extensions/    # 应用级扩展目录(模板中为空)
│   └── index.ts       # 服务端生命周期入口
├── tsconfig.json      # TypeScript 编译配置
└── package.json       # 依赖与 npm scripts

examples/empty/package.json 可以看到该模板的运行前提:

  • Node 版本要求"node": ">=20.0.0 <=26.x.x""npm": ">=6.0.0"engines 字段);
  • 核心依赖@strapi/strapi@strapi/plugin-users-permissions(本仓库内均以 workspace:* 引用源码包)、better-sqlite3(SQLite 驱动)、以及管理面板所需的 reactreact-domreact-router-domstyled-components
  • 开发依赖typescript 及对应类型定义;
  • 遥测标识"strapi": { "uuid": "getstarted" } 字段用于标记该应用实例。

理解了这一骨架之后,README 中给出的四条命令就有了明确的落点。

二、快速启动:README 核心命令逐一拆解

examples/empty/README.md 将入门流程归纳为 developstartbuild 与部署四部分,全部通过 npm scripts 暴露。

1. develop:开发模式(自动重载)

npm run develop
# or
yarn develop

该命令对应 strapi develop。从源码 packages/core/strapi/src/cli/commands/develop.ts 可以看到它实际支持的完整参数集:

参数 默认值 说明
--bundler [bundler] vite 管理面板打包器,可选 webpackvite(使用 webpack 会收到弃用警告,提示迁移到 vite)
-d, --debug false 启用调试模式与详细日志
--silent false 不输出任何日志
--polling false 在网络目录中通过轮询监听文件变更
--watch-admin / --no-watch-admin 开启 是否监听管理面板热更新
--build-admin / --no-build-admin 开启 监听关闭时是否仍构建管理面板
--open true 启动后自动在浏览器打开管理面板
--install-deps true 自动安装缺失的管理面板依赖

develop 还有一个别名 devpackage.json 中的 npm run devnpm run develop 等价),并且命令内部会判断 cluster.isPrimary,主进程才会执行打包器检查与启动逻辑——这说明 strapi develop 采用了 Node.js 的 cluster 模型来组织进程。

2. start:生产模式(关闭自动重载)

npm run start
# or
yarn start

该命令对应 strapi start,启动时自动重载(autoReload)被禁用,适合部署到服务器长期运行。其 CLI 定义位于 packages/core/strapi/src/cli/commands/start.ts,与 develop 命令同属 packages/core/strapi/src/cli/commands/ 命令族。

3. build:仅构建管理面板

npm run build
# or
yarn build

对应 strapi build,只执行管理面板前端的构建产物生成,不启动服务,常用于 CI/CD 流水线中的构建阶段。

4. 部署:strapi deploy

README 的 Deployment 部分给出了部署入口命令:

yarn strapi deploy

在 empty 模板的 package.json 中,deploystrapiconsole 三个脚本也一并被暴露:

"scripts": {
  "build": "strapi build",
  "console": "strapi console",
  "deploy": "strapi deploy",
  "dev": "strapi develop",
  "develop": "strapi develop",
  "start": "strapi start",
  "strapi": "strapi",
  "upgrade": "npx @strapi/upgrade latest",
  "upgrade:dry": "npx @strapi/upgrade latest --dry"
}

其中 npm run strapi 允许直接透传任意 strapi 子命令;upgrade / upgrade:dry 两个脚本则提供了通过 @strapi/upgrade 升级应用(--dry 表示只做预演不实际执行)的能力。

三、配置层深读:config/ 目录全解

empty 模板在 examples/empty/config/ 下提供了七个 TypeScript 配置文件,每一个都展示了 Strapi 配置函数的标准形态——接收 { env } 参数并返回类型化配置对象。

1. server.ts:监听地址与应用密钥

examples/empty/config/server.ts 定义了服务监听行为:

const serverConfig = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Server => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  app: {
    keys: env.array('APP_KEYS', ['toBeModified1', 'toBeModified2']),
  },
});
  • HOST 默认 0.0.0.0,即监听所有网络接口,容器化部署友好;
  • PORT 默认 1337,即 Strapi 的经典端口;
  • APP_KEYS 用于会话等加密操作,默认值 toBeModified* 明确提示生产环境必须替换。

2. admin.ts:后台密钥与功能开关

examples/empty/config/admin.ts 集中管理后台安全相关的四类密钥与三个功能标志:

环境变量 用途
ADMIN_JWT_SECRET 后台登录态 JWT 签名密钥
API_TOKEN_SALT API Token 加盐
ENCRYPTION_KEY 敏感配置项的对称加密密钥
TRANSFER_TOKEN_SALT 数据导入导出(transfer)token 加盐
FLAG_NPS / FLAG_PROMOTE_EE / FLAG_DOC_LINKS 控制 NPS 调研、EE 推广入口、文档链接的展示开关

所有密钥都给了 example-* 占位默认值,同样意在提醒:真实项目必须通过环境变量注入。

3. api.ts:REST 查询默认行为

examples/empty/config/api.ts 只有十余行,却决定了内容 API 的分页语义:

const config: Core.Config.Api = {
  rest: {
    defaultLimit: 25,   // 未传 limit 时每页返回 25 条
    maxLimit: 100,      // limit 上限 100
    withCount: true,    // 响应 meta 中附带 total
  },
};

4. middlewares.ts:中间件执行顺序

examples/empty/config/middlewares.ts 按固定顺序声明了九个核心中间件:strapi::loggerstrapi::errorsstrapi::securitystrapi::corsstrapi::poweredBystrapi::querystrapi::bodystrapi::sessionstrapi::faviconstrapi::public。这个顺序本身有讲究:日志与错误处理最先,安全与 CORS 前置,请求体解析(body)在查询(query)之后、会话(session)之前,静态资源(public)兜底在末尾。

5. database.ts:三数据库客户端的完整实现

examples/empty/config/database.ts 是模板中信息密度最高的配置文件,完整覆盖了 SQLite、MySQL、PostgreSQL 三种客户端:

  • 客户端选择env('DATABASE_CLIENT', 'sqlite'),默认使用零外部依赖的 SQLite;并通过 isDatabaseClientKind(来自 packages/core/database@strapi/database)做合法性校验,非法值直接抛出 Unsupported DATABASE_CLIENT 错误,把配置错误暴露在启动阶段而非运行期。
  • SQLite 分支filename 指向 env('DATABASE_FILENAME', '.tmp/data.db'),即项目内 .tmp 目录下的本地文件,并设置 useNullAsDefault: true
  • MySQL 分支:默认端口 3306,库名/用户/密码默认均为 strapi,支持完整 SSL 参数组(DATABASE_SSL_KEYDATABASE_SSL_CERTDATABASE_SSL_CADATABASE_SSL_CAPATHDATABASE_SSL_CIPHERDATABASE_SSL_REJECT_UNAUTHORIZED)。
  • PostgreSQL 分支:默认端口 5432,额外支持 DATABASE_SCHEMA(默认 public)与 DATABASE_URL 连接串两种配置方式。
  • 连接池与超时:三个客户端统一配置 pool: { min: DATABASE_POOL_MIN(2), max: DATABASE_POOL_MAX(10) },并在 connection 上附加 acquireConnectionTimeoutDATABASE_CONNECTION_TIMEOUT,默认 60000ms)。

这套"env 驱动 + 类型化返回 + 启动期校验"的写法,是 Strapi v5 配置体系的典型范式。

6. plugins.ts 与 features.ts:留白即默认

examples/empty/config/plugins.tsexamples/empty/config/features.ts 都返回空对象 {}——这正是"empty"二字的含义:不覆盖任何插件配置、不启用任何额外功能,全部走 Strapi 内核默认值。

四、入口文件:生命周期钩子与面板引导

1. src/index.ts:服务端 register / bootstrap

examples/empty/src/index.ts 导出了标准的双钩子结构:

  • register({ strapi }):应用初始化之前运行,适合扩展代码(如注册自定义服务);
  • bootstrap({ strapi }):应用启动前运行,适合初始化数据模型、执行定时任务或特殊逻辑。

模板中两者都是空实现,但类型注释 Core.Strapi 明确了钩子参数签名。

2. src/admin/app.tsx:管理面板前端引导

examples/empty/src/admin/app.tsx 是管理面板的前端入口,声明了 locales: ['fr'](声明需要打包的法语文案)与一个会打印 app 对象的 bootstrap 回调。该文件由前端构建链路处理,而非服务端编译。

五、TypeScript 编译边界:tsconfig.json 的两个关键排除

examples/empty/tsconfig.json 采用 strict: truemodule: CommonJStarget: ES2019 的编译配置,并通过 exclude 划定了服务端编译的边界:

  • 排除 src/admin/:管理面板文件不参与服务端编译(前端走独立的 vite 构建,develop 命令默认使用 vite 打包器);
  • 排除 src/plugins/****/*.test.*.tmp/.strapi/:避免运行时生成物与测试代码混入产物。

这意味着修改 src/index.tssrc/admin/app.tsx 后,两条构建链路的生效方式不同:前者随服务重启生效,后者依赖 develop 的热监听(--watch-admin 默认开启)。

六、小结

examples/empty 的价值不在于功能,而在于它用最少的代码呈现了 Strapi 应用的标准契约:develop/start/build/deploy 四类命令(其参数细节可从 develop 命令实现 直接查证)、七个配置文件各自负责的领域(端口、密钥、分页、中间件顺序、数据库)、以及 register/bootstrap 双钩子加前后端分离的双入口结构。拿到这个模板后,往 src/api/ 中添加内容类型、按需打开 config/plugins.ts,即可平滑演进为一个生产级 Headless CMS 项目。

登录后查看全文
热门项目推荐
相关项目推荐