Strapi TypeScript 示例项目实战:从 CLI 命令到完整项目配置解析(kitchensink-ts)
本文以 Strapi 仓库内置的 examples/kitchensink-ts 官方 TypeScript 示例工程为主体,围绕该示例 README 中介绍的核心能力展开:如何使用 Strapi CLI 的 develop、start、build 三条命令启动与构建项目,并进一步结合示例工程中的配置文件、应用入口与 TypeScript 配置,给出一个可直接参考的 Strapi TS 项目落地结构。读完本文,你将掌握 Strapi 示例工程的目录组织方式、各配置文件的类型化写法,以及三条 CLI 命令对应的底层脚本映射。
一、示例工程定位与目录结构
examples/kitchensink-ts 是 Strapi 源码仓库中用于演示 TypeScript 环境下完整 Strapi 应用的示例工程。与同目录下的 examples/getstarted(JavaScript 版本)等示例不同,该工程全部后端代码、配置文件和管理端扩展代码均使用 TypeScript 编写,适合作为新项目脚手架的参照模板。
工程的整体目录结构如下(均相对仓库根目录):
| 路径 | 作用 |
|---|---|
| config/ | 五个核心配置文件:admin.ts、api.ts、database.ts、middlewares.ts、server.ts |
| src/index.ts | 应用入口,导出 register / bootstrap 两个生命周期钩子 |
| src/admin/app.example.tsx | 管理面板扩展示例(locales 配置与前端 bootstrap 钩子) |
| src/admin/webpack.config.example.ts | 管理面板 webpack 自定义示例 |
| src/api/ | 内容类型(Content-Types)与控制器代码目录,示例中为空 |
| src/extensions/ | 自定义扩展(extensions)目录 |
| public/uploads/ | 本地文件上传的默认落盘目录 |
| tsconfig.json | 后端(CommonJS)TypeScript 编译配置 |
| package.json | 脚本命令、依赖与 Node 版本约束 |
值得注意的是,package.json 的依赖中使用了 workspace:* 协议引用 @strapi/strapi 与 @strapi/plugin-users-permissions,说明该工程位于 Strapi 仓库的 yarn workspaces 体系内,可直接引用源码中的 Strapi 核心包,这正是示例工程能随仓库版本同步演进的实现方式。
二、三条核心 CLI 命令:develop / start / build
示例 README(examples/kitchensink-ts/README.md)开篇即指出:Strapi 自带功能完整的命令行工具(CLI),可以在数秒内完成项目的脚手架搭建与日常管理。工程提供的三条核心命令如下。
2.1 develop:开发模式启动(启用 autoReload)
npm run develop
# or
yarn develop
以自动热重载(autoReload)模式启动 Strapi 应用,适合开发阶段使用:修改代码后应用会自动重新加载,无需手动重启进程。
2.2 start:生产模式启动(禁用 autoReload)
npm run start
# or
yarn start
以关闭 autoReload 的模式启动应用,是部署与生产运行对应的启动方式。
2.3 build:构建管理面板
npm run build
# or
yarn build
构建(admin panel)管理后台前端产物,产出供 start 直接伺服的前端静态资源。
2.4 命令背后的脚本映射
从 package.json 的 scripts 字段可以看到,上述三条 npm 脚本实际上是一比一映射到 Strapi CLI 的同名子命令:
{
"scripts": {
"build": "strapi build",
"develop": "strapi develop",
"start": "strapi start",
"strapi": "strapi"
}
}
其中额外的 "strapi": "strapi" 脚本允许通过 npm run strapi -- <子命令> 调用 CLI 的其他能力(如创建内容类型、初始化工程结构等)。从源码结构看,CLI 子命令的实现位于仓库的 packages/core/strapi 包中,该包即 @strapi/strapi 核心入口,负责解析参数、加载 config/ 下的配置文件并驱动应用生命周期;本文所介绍的三条命令均由该包提供的 strapi 可执行文件分发执行。
三、五个核心配置文件详解
示例工程将配置全部集中在 config/ 目录下,且每个文件都通过 import type { Core } from '@strapi/strapi' 引入 Strapi 官方类型,实现类型化配置——这是 TypeScript 示例相对 JavaScript 示例(如 examples/getstarted/config/)最显著的优势:配置文件获得完整的参数补全与类型检查。以下逐文件说明。
3.1 admin.ts:管理面板配置
config/admin.ts 完整内容如下:
import type { Core } from '@strapi/strapi';
const adminConfig = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Admin => ({
auth: {
secret: env('ADMIN_JWT_SECRET', 'example-token'),
},
apiToken: {
salt: env('API_TOKEN_SALT', 'example-salt'),
},
transfer: {
token: {
salt: env('TRANSFER_TOKEN_SALT', 'example-salt'),
},
},
flags: {
nps: env.bool('FLAG_NPS', true),
promoteEE: env.bool('FLAG_PROMOTE_EE', true),
docLinks: env.bool('FLAG_DOC_LINKS', true),
},
});
export default adminConfig;
关键参数:
auth.secret:管理员 JWT 的签名密钥,生产环境必须通过环境变量ADMIN_JWT_SECRET注入,示例中的example-token仅为占位值;apiToken.salt:API Token 加盐哈希用的盐值;transfer.token.salt:数据迁移(data transfer)令牌加盐值;flags:若干功能开关,支持通过FLAG_NPS、FLAG_PROMOTE_EE、FLAG_DOC_LINKS环境变量覆盖,例如设置FLAG_DOC_LINKS=false可关闭后台文档外链。
该文件还演示了 Strapi 配置系统的一个核心机制:配置导出的是函数(接收 { env } 参数),而非静态对象。env 系列读取器定义在类型包的 packages/core/types/src/core/config/shared.ts 中,env() 读取字符串、env.bool() 读取布尔、env.int() 读取整数、env.array() 读取数组,第二个参数为默认值。这种设计使得同一份代码可以在不同部署环境(开发/生产)下通过环境变量差异化取值。
3.2 api.ts:REST API 行为配置
config/api.ts 配置 REST 接口的默认分页与响应行为:
const config: Core.Config.Api = {
rest: {
defaultLimit: 25,
maxLimit: 100,
withCount: true,
},
};
defaultLimit: 25:列表接口未显式指定pagination[limit]时,每页默认返回 25 条;maxLimit: 100:客户端可请求的每页条数上限;withCount: true:响应中附带总条数统计,便于前端渲染分页器。
3.3 database.ts:数据库连接配置(SQLite)
config/database.ts 展示了 SQLite 连接配置的完整写法:
const config = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Database<'sqlite'> => {
const connection: Core.Config.Database<'sqlite'>['connection'] = {
client: 'sqlite',
connection: {
filename: path.join(__dirname, '..', '..', env('DATABASE_FILENAME', '.tmp/data.db')),
},
useNullAsDefault: true,
};
return {
connection,
};
};
client: 'sqlite'与类型参数Core.Config.Database<'sqlite'>互相印证,类型系统按驱动区分了各数据库的连接结构;- 数据库文件路径通过
path.join(__dirname, '..', '..', ...)锚定到工程根目录下的.tmp/data.db,并允许用DATABASE_FILENAME环境变量覆盖; useNullAsDefault: true是 SQLite 驱动下的兼容性选项。
该文件同时说明:切换数据库(如 PostgreSQL、MySQL)时只需替换 client 与 connection 结构,类型参数会随之变化,Strapi 的类型体系会给出对应的连接字段约束。
3.4 server.ts:服务与密钥配置
config/server.ts 控制 HTTP 服务监听与 Cookie 密钥:
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/port:默认监听0.0.0.0:1337,即 Strapi 的默认端口 1337;app.keys:Cookie 签名密钥数组,支持多密钥轮换;示例值toBeModified1/2明确提示生产部署前必须修改为APP_KEYS环境变量的真实值。
3.5 middlewares.ts:中间件执行顺序
config/middlewares.ts 以字符串数组声明了请求处理的中间件链:
const config: Core.Config.Middlewares = [
'strapi::logger',
'strapi::errors',
'strapi::security',
'strapi::cors',
'strapi::poweredBy',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
每个 strapi:: 前缀项指向核心内置中间件,数组顺序即 Koa 中间件的执行顺序:先记日志、统一错误处理与设置安全头,再处理 CORS、响应头、参数解析(query/body)、会话与静态资源。新增自定义中间件时,将其插入合适的位置即可改变其在请求生命周期中的执行时机。
四、应用入口与生命周期钩子
src/index.ts 是 Strapi 应用的服务端入口,导出两个异步钩子:
import '@strapi/strapi';
export default {
register(/*{ strapi }*/) {},
bootstrap(/*{ strapi }*/) {},
};
register:在应用初始化之前运行,用于扩展内部代码逻辑(如注册全局服务、修改初始化流程);bootstrap:在应用启动完成之前运行,适合初始化数据模型、跑定时任务或执行特殊启动逻辑。
两个钩子均以 { strapi } 实例为参数(示例中注释掉了参数),可以在其中访问完整的 Strapi 实例 API。文件首行的 import '@strapi/strapi' 用于引入核心的副作用初始化逻辑。
五、管理面板扩展:locales 与前端 bootstrap
管理后台的定制代码放在 src/admin/ 目录。示例文件 app.example.tsx 演示了两类管理端扩展点:
import type { StrapiApp } from '@strapi/strapi/admin';
export default {
config: {
locales: [
// 'fr', 'de', 'es', 'ja', 'zh-Hans', 'zh', ...(示例中注释了可选语言列表)
],
},
bootstrap(app: StrapiApp) {
console.log(app);
},
};
config.locales:声明后台界面支持的语言列表,取消注释即可启用对应 locale;bootstrap(app: StrapiApp):管理前端应用初始化时执行,参数是类型化的StrapiApp实例,可用于注入全局组件、覆写路由或修改面板行为。
同目录下的 webpack.config.example.ts 则预留了自定义构建管线的示例位置。需要留意的是,这些文件以 .example 命名,属于示例性质:实际启用扩展时需按 Strapi 的 admin 扩展约定将其落为正式入口文件后再构建。
六、双 tsconfig 设计:后端 CommonJS 与前端 ESNext
该示例工程存在两套独立的 TypeScript 配置,分别服务前后端两种构建目标,这是理解 Strapi TS 项目构建机制的关键。
6.1 后端(服务端)tsconfig
根目录 tsconfig.json 面向运行在 Node.js 中的服务端代码:
{
"compilerOptions": {
"outDir": "dist",
"rootDir": ".",
"module": "CommonJS",
"moduleResolution": "Node",
"lib": ["ES2020"],
"target": "ES2019",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"incremental": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"noEmitOnError": true,
"noImplicitThis": true
},
"include": ["./", "src/**/*.json"],
"exclude": [
"node_modules/", "build/", "dist/", ".cache/", ".tmp/",
".strapi/", "src/admin/", "**/*.test.ts", "src/plugins/**"
]
}
要点:
module: CommonJS+moduleResolution: Node:服务端产物为 CommonJS,与 Node 运行时匹配;target: ES2019、lib: ES2020:语言特性基线;noEmitOnError: true配合incremental: true:类型错误即阻断产物输出,且增量编译提升二次构建速度;exclude中显式排除了src/admin/——前端代码不进入这套编译目标。
6.2 管理前端 tsconfig
src/admin/tsconfig.json 则面向由 webpack/bundler 打包的前端代码:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"jsx": "react-jsx",
"noEmit": true,
"strict": true
},
"include": ["../plugins/**/admin/src/**/*", "./"],
"exclude": ["node_modules/", "build/", "dist/", "**/*.test.ts"]
}
要点:module: ESNext + moduleResolution: Bundler 说明前端模块由打包器解析;jsx: react-jsx 匹配 React 18 的自动 JSX 运行时;noEmit: true 表示它只做类型检查,产物交由 strapi build 的 webpack 管线生成。include 同时纳入了 ../plugins/**/admin/src/**/*,即本地插件的 admin 源码也参与这套前端检查。
这种"一个工程、两套 tsconfig"的划分,与 package.json 中 react、react-dom、react-router-dom、styled-components 四个前端依赖共存于后端依赖列表的做法相互印证:Strapi 示例工程将前后端依赖合并声明,由构建流程按目录边界区分用途。
七、运行环境与依赖约束
package.json 明确声明了运行环境要求,在部署前必须满足:
"engines": {
"node": ">=20.0.0 <=26.x.x",
"npm": ">=6.0.0"
}
即 Node.js 版本需落在 >=20.0.0 且不超过 26.x.x 区间。其他关键依赖及其作用:
| 依赖 | 版本 | 用途 |
|---|---|---|
@strapi/strapi |
workspace:* |
核心框架(含 CLI、服务、管理面板) |
@strapi/plugin-users-permissions |
workspace:* |
用户与权限插件(注册、登录、Token) |
better-sqlite3 |
12.8.0 |
SQLite 数据库驱动,对应 database.ts 中 client: 'sqlite' |
react / react-dom |
18.3.1 |
管理面板前端运行时 |
react-router-dom |
6.30.4 |
管理面板路由 |
styled-components |
6.4.1 |
管理面板样式方案 |
数据库方面,示例默认使用 SQLite(文件落盘在工程根目录的 .tmp/data.db),开箱即用无需外部服务;如需切换到 PostgreSQL/MySQL 等,按 3.3 节的 database.ts 模式替换连接配置,并在 dependencies 中增加对应驱动(仓库其他示例工程如 examples/complex/scripts/ 下即提供了面向 Postgres/MySQL/MariaDB/SQLite 的多数据库调试脚本,可作参照)。
八、部署建议
README 的 Deployment 部分指出 Strapi 提供多种部署选项。基于本文分析的项目结构,一条最小可行的部署路径为:
- 通过环境变量注入生产密钥:
ADMIN_JWT_SECRET、API_TOKEN_SALT、APP_KEYS,并将DATABASE_FILENAME指向持久化存储位置(若使用外部数据库则替换database.ts连接); - 执行
npm run build构建管理面板前端产物; - 执行
npm run start以禁用 autoReload 的模式启动服务,默认监听0.0.0.0:1337,可用HOST/PORT覆盖; - 静态上传文件默认写入工程内
public/uploads/目录,部署时需保证该目录可写并持久化,或改用仓库examples/complex/config中演示的对象存储类 provider 方案。
九、小结
examples/kitchensink-ts 以最小的文件集合完整演示了 Strapi TypeScript 项目的标准形态:三条 CLI 命令(develop / start / build)经由 package.json 的脚本映射到 strapi 子命令;config/ 下五个类型化配置文件覆盖管理面板、REST API、数据库、服务参数与中间件链;src/index.ts 与 src/admin/app.example.tsx 分别提供前后端两类生命周期扩展点;双 tsconfig 设计划定了 CommonJS 服务端与 ESNext 前端两条构建边界。将本文各节的配置与命令组合使用,即可把一个空的 Strapi TS 工程从零启动、定制到部署。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00