Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

创建项目

Oak 项目的推荐创建方式,是直接使用 oak-cli 生成一个完整的工程骨架。这样生成出来的目录结构、脚本、依赖配置和多端入口都是符合 Oak 规范的,后续再去阅读本书中的其它章节时,也更容易一一对应起来。

如果你是第一次接触 Oak,建议先从新手入门:从零完成一个任务清单应用开始。那一章会从本命令开始,连续完成安装依赖、定义实体、生成领域代码、编写页面 CRUD、初始化数据库和添加其它端;本页适合在完成第一次实践后回来查阅创建选项。

创建命令

在你准备放置项目的目录下执行:

oak-cli create my-first-oak-app

oak-cli 在源码中的入口定义位于 oak-cli/src/index.ts,创建项目的实现位于 oak-cli/src/create,其中核心命令是:

program
    .command('create <name>')
    .option('-d, --dev', 'dev')
    .option('-m, --module', 'module')
    .action(create);

其中:

  • create <name>:创建一个完整的 Oak 应用工程;
  • --dev:按 Oak 家族仓库的本地联调方式生成依赖,适合你当前这种直接维护框架源码的开发环境;
  • --module:只创建一个 Oak 模块,而不是完整应用。模块模式下不会生成 webwechatMp 等前端工程骨架,适合编写一个可复用的业务包。

创建过程中会询问什么

执行创建命令后,oak-cli/src/create/index.ts 会进一步询问一些信息:

  • 项目显示名 title
  • 版本号 version
  • 项目描述 description
  • 应用需要的数据库驱动:MySQL、PostgreSQL、SQLite,至少选择一个,默认 MySQL
  • 是否默认依赖 oak-general-business
  • 是否还依赖其它 Oak 家族模块
  • 是否加载一个示例工程

其中最值得新手注意的是 oak-general-business。它是 Oak 官方抽象出来的一套通用业务逻辑,包含了用户、应用、会话、文件、微信、OAuth 等大量基础能力。绝大多数业务项目在一开始都应该勾选它,后面本书最后一章也会专门介绍它。

创建命令不会再询问平台多选。完整应用默认只生成 Web workspace;微信小程序、React Native、Desktop 在项目创建后按需通过 oak-cli add 添加。数据库驱动选择只出现在应用模式,模块模式不会生成数据库配置。

--dev 和普通模式的区别

如果使用 --dev,生成出来的 package.json 会把 Oak 家族依赖指向本地相邻目录,例如:

"oak-domain": "file:../oak-domain",
"oak-frontend-base": "file:../oak-frontend-base",
"oak-cli": "file:../oak-cli"

这正是当前 Oak 仓库的常见开发方式。也就是说,如果你要在本地同时修改 oak-domainoak-frontend-baseoak-general-business 等库,那么项目目录最好和这些仓库处在同一级目录下,否则这些本地依赖路径就无法正确解析。

如果不使用 --devoak-cli 会从 npm 上读取 Oak 家族包的最新版本,并写入 semver 版本号。此时后续 make:domain 读取的是发布包实体产物,优先级为 es/entities -> lib/entities -> src/entities

新发布的 Oak 模块不应该靠发布 src 解决编译问题。发布包应带上 es/entities/*.d.ts 和同名 .js,编译器会自动合并类型声明和运行时值。

创建命令实际做了什么

oak-cli/src/create/index.ts 会完成下面这些事情:

  1. 检查目标目录是否已经存在;
  2. 复制模板目录;
  3. 在完整应用模式下生成默认 web workspace;小程序、React Native 和 Desktop workspace 留给后续 oak-cli add
  4. 生成 oak.config.jsonoak.config.ts,前者保存项目运行/检查配置,后者保存当前 Vite / webpack / alias / CDN 等编译配置;
  5. 生成 tsconfig.lib.jsontsconfig.es.jsonsrc/tsconfig.jsontsconfig/paths.*.jsonweb/tsconfig.json;新增平台时再生成对应 workspace 配置;
  6. 生成 package.json、Oak 默认脚本、推荐 Web CDN 配置、可选 build:bundle 和升级脚本入口;
  7. 把你选择的依赖写入 src/configuration/dependency.ts
  8. 在页面、组件和 Web 命名空间目录中放置 index.config.ts,作为新项目的结构化配置入口;
  9. 将模板中的默认项目名统一重命名为你输入的名字;
  10. 根据数据库选择只保留对应驱动依赖和 configuration/mysql.jsonpostgres.jsonsqlite.json
  11. 如果勾选示例,额外复制一套示例业务代码。

因此,Oak 的“创建项目”并不是单纯地拷贝几份空文件,而是顺手把后续最关键的开发基础设施一起准备好了。

新项目里的配置入口

当前模板已经不再建议把页面、组件和命名空间配置继续散落在 index.json 里。新项目应优先使用同目录下的 index.config.ts

import { CreatePageConfig } from '@oak-frontend-base/config';
import { CreateComponentConfig } from '@oak-frontend-base/config';
import { CreateNamespaceConfig } from '@oak-frontend-base/config';

三类配置入口的职责不同:

  • src/pages/**/index.config.ts:页面配置,使用 CreatePageConfig。这里声明 Web 路由、菜单、访问控制以及小程序页面 JSON 能力。
  • src/components/**/index.config.ts:组件配置,使用 CreateComponentConfig。这里声明小程序组件 JSON 能力,例如 usingComponentscomponentGenericsstyleIsolation
  • web/src/app/namespaces/<namespace>/index.config.ts:Web 命名空间配置,使用 CreateNamespaceConfig。这里声明命名空间路由入口、菜单分组、默认访问策略和控制台上下文实体范围。

index.json 仍然是兼容入口,旧项目可以继续读取;但新页面、新组件和新命名空间都应该把配置写进 index.config.ts。小程序相关 JSON 字段放在 mp 字段下,由 oak-cli 在构建时生成最终的页面或组件 JSON。

命名空间目录还会配合一个生成文件:

web/src/app/namespaces/
├── console/
│   └── index.config.ts
├── frontend/
│   └── index.config.ts
├── allNamespaceConfigs.ts
└── index.ts

其中 allNamespaceConfigs.tsoak-cli 根据命名空间配置和页面菜单配置生成,不应该手工维护;index.ts 负责重新导出聚合结果;web/src/index.tsx 会把它传给 oak-frontend-base/platforms/web/initializenamespaceConfigs 参数。

创建完成后的第一步

项目创建完成后,建议按下面的顺序继续:

npm install
npm run dev

这三步分别对应:

  • 安装依赖,并由 postinstall 顺序执行 project:initmake:domainmake:dep
  • 同时启动后端 server:start 和 web 端 start:web 进行联调。

当前模板的普通应用会把 postinstall 配成 npm run project:init && npm run make:domain && npm run make:dep。因此首次 npm install 后通常已经完成依赖模板初始化、领域代码和依赖装配生成。后续如果增删 Oak 依赖模块,仍应显式按这个顺序重新执行,保证依赖模板先落盘、领域类型包含最终实体、装配代码最后生成。

创建应用和创建模块

很多初学者一开始会分不清 Oak 应用和 Oak 模块。

二者的区别可以先简单理解为:

  • Oak 应用:最终可以独立运行,有自己的前端入口、后端入口、数据库配置和部署流程;
  • Oak 模块:只提供实体、逻辑、特性、页面或组件,供别的 Oak 应用依赖。模块保留跨端源码和类型基线,但不生成可独立运行的平台 workspace。

例如 oak-general-business 就是一个典型的模块,而 bm-smart 是一个完整应用。Oak 的依赖编译能力,正是为了把这两种代码组织方式统一起来。

所以如果你的目标是“做一个业务系统”,请优先创建完整应用;如果你的目标是“沉淀一套可复用业务包”,再考虑使用 --module

一个推荐的最小起步方式

如果你是第一次接触 Oak,最推荐的起步方式其实非常简单:

  1. 在 Oak 家族仓库同级目录下执行 oak-cli create xxx --dev
  2. 依赖 oak-general-business
  3. 执行 npm install;当前模板会在 postinstall 中完成 project:initmake:domainmake:dep
  4. npm run dev 同时启动后端和 web;
  5. 编写一个最小的 Entity 和一个最小的页面。

这样学习曲线是最平缓的,也符合当前 Oak “开发时就使用真实后端运行态”的默认模板。旧的纯前台模式已经移除,不要再按 start:web 单独替代后端来理解。

需要其它平台时,再按多平台工作区添加,不必在创建当天把所有原生工具链一并安装。