首页
/ Strapi example-js 模板实战:从 develop 启动、build 构建到 strapi deploy 部署的完整工程链路

Strapi example-js 模板实战:从 develop 启动、build 构建到 strapi deploy 部署的完整工程链路

2026-09-06 12:16:14作者:钟日瑜

本篇基于 Strapi 仓库中 create-strapi-app CLI 的 JS 示例模板(packages/cli/create-strapi-app/templates/example-js)及其自带的 README.md 展开。该文档是脚手架生成的 Strapi 应用根目录下的"上手指南",核心讲 developstartbuild 三个常用命令与 strapi deploy 部署流程。读完本文,你将不仅知道如何启动一个 Strapi 示例项目,还能深入理解模板的脚本映射、环境变量驱动的数据库/服务配置,以及种子脚本 seed.js 的首次运行检测与内容导入机制。

模板定位:create-strapi-app 的 JS 示例工程

create-strapi-app 是 Strapi 官方脚手架包,package.json 中声明其职责为 "Generate a new Strapi application.",当前仓库内版本为 5.52.2,要求 Node.js >=20.0.0 <=26.x.x。该包通过 files 字段把 templates/ 目录一并发布,仓库中提供了四套模板:

  • packages/cli/create-strapi-app/templates/vanilla / vanilla-js:空白项目;
  • packages/cli/create-strapi-app/templates/example / example-js:预置文章、作者、分类等内容模型与种子数据的示例项目。

example-js 是面向 JavaScript 开发者的示例工程,其根目录结构(以仓库实际内容为准)为:

example-js/
├── config/          # admin.js、api.js、database.js、middlewares.js、plugins.js、server.js
├── data/            # data.json 种子数据 + uploads/ 示例媒体文件
├── database/        # migrations/ 数据库迁移目录
├── public/uploads/  # 运行时上传目录
├── scripts/seed.js  # 种子脚本
├── src/             # admin/、api/、components/、extensions/、index.js
├── jsconfig.json
├── package.json
└── README.md        # 即本篇的关联文档

其中 src/api/ 下内置了 aboutarticleauthorcategoryglobal 五个内容类型(各自包含 content-typescontrollersroutesservices 四层文件),src/components/shared/ 下则提供了 mediaquoterich-textseoslider 五个可复用组件。这套模型让示例项目开箱即是一个可浏览的博客内容站,也决定了种子脚本需要导入哪些数据。

develop:开发模式启动(autoReload 开启)

模板 README 的第一个命令是 develop,用于以开启 autoReload 的方式启动应用,适合本地开发时热重载配置与代码变更:

npm run develop
# or
yarn develop

对照 package.json,这条 npm script 的真实映射是:

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

npm run develop 最终执行的是 Strapi 内置 CLI 的 strapi develop 子命令。注意这里同时保留了 dev 别名,两条命令等价。

start:生产模式启动(autoReload 关闭)

第二个命令是 start,以关闭 autoReload 的方式启动应用,对应生产环境运行场景:

npm run start
# or
yarn start

映射关系同样是 strapi startdevelopstart 的区别仅在是否开启自动重载:前者监听文件变化并自动重启,便于开发迭代;后者以固定加载态运行,行为可预期,适合作为部署后的常驻进程。从模板脚本结构看,二者共用同一份 config/src/,差异只体现在 CLI 层的运行策略上。

build:构建管理后台(admin panel)

第三个命令用于构建后台管理面板的静态资源:

npm run build
# or
yarn build

映射为 strapi build。Strapi 的 admin 端是基于前端工程打包的 SPA,构建产物随应用一起分发;example-jssrc/admin/ 目录中带有 app.example.jsvite.config.example.js 两个示例文件,作为管理员面板定制(插件注册、Vite 配置扩展)的起点,默认处于 .example 示例态、不参与运行。

模板中的其他实用脚本

除 README 重点介绍的三个命令外,package.json 还预置了若干工程化脚本,实际使用示例项目时值得关注:

脚本 实际命令 用途
npm run console strapi console 打开 Strapi 交互式控制台,直接调用 strapi 运行时 API
npm run seed:example node ./scripts/seed.js 导入模板种子数据(内容 + 媒体)
npm run upgrade npx @strapi/upgrade latest 执行 Strapi 升级流程
npm run upgrade:dry npx @strapi/upgrade latest --dry 以 dry-run 模式预演升级,不落盘
npm run deploy strapi deploy 执行部署(见下文)
npm run strapi ... strapi ... 透传任意 Strapi CLI 子命令

配置层:环境变量驱动的服务与数据库

develop/start 启动时加载的核心配置都在 config/ 目录。

服务配置 server.js

server.js 决定 API 服务监听行为:

module.exports = ({ env }) => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  app: {
    keys: env.array('APP_KEYS'),
  },
  webhooks: {
    populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),
  },
});
  • 默认监听 0.0.0.0:1337,Strapi 的 1337 端口由此而来,可用 HOST/PORT 环境变量覆盖;
  • APP_KEYS 是逗号分隔的签名密钥数组,用于 API Token 等签名场景;
  • WEBHOOKS_POPULATE_RELATIONS 控制 Webhook 载荷是否展开关系字段,默认 false

管理端配置 admin.js

admin.js 集中了后台安全相关的密钥,全部来自环境变量:

  • ADMIN_JWT_SECRET:管理员会话 JWT 签名密钥;
  • API_TOKEN_SALT:API Token 派生盐值;
  • TRANSFER_TOKEN_SALT:数据迁移/传输令牌盐值;
  • ENCRYPTION_KEY:管理端敏感信息加密密钥;
  • flags 下的 npspromoteEEdocLinks 三个布尔开关控制后台内的调研问卷、EE 推广与文档链接展示,均可通过 FLAG_NPSFLAG_PROMOTE_EEFLAG_DOC_LINKS 关闭。

数据库配置 database.js

database.js 展示了模板对多数据库的完整支持,支持 sqlite(默认)、mysqlpostgres 三种 DATABASE_CLIENT,并带有校验逻辑:

const client = env('DATABASE_CLIENT', 'sqlite');

if (!isDatabaseClientKind(client)) {
  throw new Error(
    `Unsupported DATABASE_CLIENT: ${client}. Use "postgres", "mysql", or "sqlite".`
  );
}

三种连接的要点:

  • sqlite(默认):文件型数据库,默认落在项目相对路径 .tmp/data.dbpath.join(__dirname, '..', env('DATABASE_FILENAME', '.tmp/data.db'))),useNullAsDefault: true
  • mysql:默认 localhost:3306,库名 strapi,用户/密码 strapi,连接池 min=2, max=10DATABASE_POOL_MIN/DATABASE_POOL_MAX),支持 DATABASE_SSL 及其 key/cert/ca 等证书项;
  • postgres:默认 localhost:5432,支持 DATABASE_URL 连接串与 DATABASE_SCHEMA(默认 public),SSL 配置项与 mysql 一致。

所有连接还会应用 DATABASE_CONNECTION_TIMEOUT(默认 60000 ms)作为获取连接的超时时间。这意味着本地零配置即可运行(sqlite 落盘 .tmp/),而在托管数据库环境下只需要注入 DATABASE_CLIENT 与相应连接变量。

种子数据脚本 seed.js 深度解析

npm run seed:example 执行的 scripts/seed.js 是模板最有技术含量的部分,完整演示了"如何在 Strapi 运行时之外以编程方式创建内容"。其关键机制如下:

1. 首次运行检测(plugin store 标记位)

async function isFirstRun() {
  const pluginStore = strapi.store({
    environment: strapi.config.environment,
    type: 'type',
    name: 'setup',
  });
  const initHasRun = await pluginStore.get({ key: 'initHasRun' });
  await pluginStore.set({ key: 'initHasRun', value: true });
  return !initHasRun;
}

通过 Strapi 的 plugin store 写入 initHasRun 标记,第二次运行时直接提示 "Seed data has already been imported"。从源码结构看,这是一个幂等性保护:重复导入会因唯一约束或重复内容失败,因此除非清空数据库,否则不做二次导入。

2. 打开 public 角色读取权限

setPublicPermissions 会查找 plugin::users-permissions.roletype: 'public' 的角色,然后为 articlecategoryauthorglobalabout 五个控制器批量创建 find/findOne 权限:

action: `api::${controller}.${controller}.${action}`,

这解释了为什么示例项目在启动后无需任何后台操作,前端就能匿名 GET /api/articles 等接口——种子脚本替 public 角色完成了授权。

3. 媒体上传去重与 blocks 回填

  • uploadFile 调用 strapi.plugin('upload').service('upload'),即 upload 插件的上传服务,逐文件生成 fileInfo(替代文本、标题、名称);
  • checkFileExistsBeforeUpload 先按文件名(去掉扩展名)查询 plugin::upload.file,已存在则复用,不存在才从 data/uploads/ 读文件上传,并用 mime-types 推断 MIME;
  • updateBlocks 遍历动态区(dynamic zone)的 blocks:对 shared.media 块回填单文件、对 shared.slider 块回填文件数组,其余块原样保留。

这套"先查库、后上传、按 __component 回填"的写法,正是 Strapi 动态区 + 组件模型(对应 src/components/shared/ 下的 media.jsonslider.json 等 schema)在种子脚本中的标准消费姿势。

4. 导入顺序与发布态

importSeedData 的执行顺序为:授权 → categoriesauthors(先传头像再建作者)→ articles(封面 + blocks 处理)→ global(favicon 与默认分享图)→ about。每个入口条目都显式设置 publishedAt: Date.now(),确保导入的是已发布而非草稿态,API 立即可见。

5. 独立进程启动运行时

脚本末尾 main 函数展示了脱离 Web 服务、仅加载 Strapi 运行时的标准方式:

const { createStrapi, compileStrapi } = require('@strapi/strapi');
const appContext = await compileStrapi();
const app = await createStrapi(appContext).load();
// ... 执行 seed ...
await app.destroy();

compileStrapi() 编译上下文 → createStrapi().load() 加载应用 → 执行种子逻辑 → destroy() 释放。这一模式同样适用于编写一次性数据迁移脚本。

部署:strapi deploy 与部署选项

模板 README 的部署章节指出 Strapi 支持多种部署方案,并给出核心命令:

yarn strapi deploy

对照 package.json,该命令对应 "deploy": "strapi deploy" 脚本(yarn strapi deploy 则是通过 "strapi": "strapi" 脚本透传子命令,两者等价)。部署前通常需要先执行 npm run build 产出管理后台静态资源;在数据库层面则按上文 DATABASE_CLIENT 环境变量接入目标数据库,并注入 ADMIN_JWT_SECRETAPI_TOKEN_SALTAPP_KEYS 等安全变量。仓库的 examples/ 目录与 docker-compose.dev.yml 等文件也提供了开发/测试环境组合的参考。

小结

example-js 模板 README 虽短,但它给出的 develop/start/build/deploy 四条命令覆盖了 Strapi 应用从开发到上线的完整生命周期;而围绕这份 README,模板工程内的 package.json 脚本映射、config/ 下环境变量驱动的服务与数据库配置、以及 scripts/seed.js 的运行时编程式导入,共同构成了一套可直接复制的 JS 版 Strapi 工程基线。以它为起点,替换 src/api/ 中的内容类型、调整 config/database.js 的目标数据库,即可得到属于自己的 Strapi 应用骨架。

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