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 的开发模式非常灵活,但真正部署到线上时,建议把它理解成两部分:

  • 前端产物的构建与发布;
  • 后端服务进程的编译、初始化与运行。

本地开发也应默认使用真实后端运行态。当前模板的 npm run dev 会同时启动 server:startstart:web,线上部署时则应把后端服务进程和各目标端产物分开发布。

部署前要先明确的事实

一个真正启动起来的 Oak 后端,不只是提供查询和保存数据这么简单。根据 oak-backend-base/src/AppLoader.ts 的实现,服务启动后还会继续负责:

  • 装配所有 triggerchecker 和内置逻辑;
  • 暴露 aspectendpoint
  • 注册导入导出 port
  • 每 120 秒轮询一次 watcher
  • 通过 node-schedule 运行 timer
  • 在启动和停止时执行 routines/startroutines/stop

所以,线上环境中的 Oak 后端,本质上是整个业务系统的运行核心,而不只是一个“给前端提供接口”的薄服务。

一、部署后端

1. 编译项目

先在项目根目录执行:

npm run make:domain
npm run make:locale
npm run make:dep
npm run build

如果这次发布增删了 Oak 依赖模块,先执行 npm run project:init,再执行 npm run make:domainnpm run make:dep。这一步完成后,项目中的 TypeScript 后端代码会被编译到 lib 目录。真正上线运行的 Node.js 进程,就是基于这里的代码。

已有数据库的结构变更不要直接混在 server:init 里处理。编译后先生成升级计划:

npm run db:upgrade:plan

它会在 .oak-upgrade/<时间戳> 下输出 migration.sqlrollback.sqlsummary.jsontable-changes.jsonwarnings.jsonrename-candidates.json。审核无误后,再由 DBA 或发布脚本执行结构升级。只有明确接受风险时,才使用:

npm run db:upgrade:plan -- --execute

如果计划里有 manualSqlwarningsrenameCandidates,不要直接执行;先确认是否是列/索引重命名、大表索引调整、枚举变更或需要人工拆分的 DDL。

2. 准备数据库

Oak 后端当前按数据库类型 mysql -> postgres -> sqlite 查找配置;每种类型都先检查环境文件,再检查普通文件:

configuration/mysql.${NODE_ENV}.json
configuration/mysql.json
configuration/postgres.${NODE_ENV}.json
configuration/postgres.json
configuration/sqlite.${NODE_ENV}.json
configuration/sqlite.json

找到第一份有效配置后就确定 store。项目还必须安装对应驱动:MySQL 使用 mysql2,PostgreSQL 使用 pg,SQLite 使用 better-sqlite3

本书前面已经提到过,常见做法是在项目配置中写好数据库参数,并先创建空库:

create database xxx default character set utf8mb4;

然后执行:

npm run server:init

它会根据当前项目编译后的 Storage 定义和 src/data 中的静态数据去初始化数据库。

::: danger 只能用于首次初始化 当前普通模板的 initServer.js 通常调用 AppLoader.initialize('dropIfNotStatic')。该模式会删除并重建所有非 static 实体表,再插入 seed 数据。它不是“补一条初始化数据”的增量命令,已有开发库和生产库都不能为了刷新 src/data 随手执行。

已有数据库应使用审核后的 schema migration 和明确的数据迁移;执行任何初始化脚本前,先读取项目自己的 scripts/initServer.js,确认实际 ifExists 参数。 :::

SQLite 适合本地单机工具、Desktop 配套服务和较轻量部署。最小配置示例:

{
    "filename": "data/app.sqlite",
    "poolSize": 4
}

SQLite 已支持 schema inspection 和 migration plan,但仍有方言边界,例如不支持任意列定义原地修改和数据库 view。升级时同样先审核 db:upgrade:plan,不要把它当作无结构数据库。

3. 启动服务

npm run server:start

此命令启动的就是正式的 Oak 后端运行进程。通常线上环境还会再用 pm2systemd、容器编排系统等方式去守护这个进程,这一层属于通用 Node.js 运维能力,并不是 Oak 特有的部分。

4. 可选的 server bundle

新项目还提供:

npm run build:bundle

它使用 esbuild 生成独立的后端部署目录,主要包含:

dist/
├── server.js
├── package.json
├── server-metafile.json
├── target/
├── configuration/
└── oak-packages/

项目根的 pm2.*.json 会按原名复制;构建器不会生成固定的 pm2.prod.config.json。启动、初始化和升级命令都由 dist/package.json 指向本地入口:

node server.js
node server.js initialize
node server.js db:upgrade:plan

Server bundle 当前是 opt-in 路径,不替代普通 build:lib。部署前检查:

  • configuration/*.json 是否已按环境安全提供,且没有把密码配置提交到仓库;
  • 目标数据库驱动是否进入部署环境;
  • server.nodeModules.bundle 与第三方依赖安装策略是否一致;
  • Oak 包是否按 package.json.oak.package 输出到 dist/oak-packages
  • 动态 require、原生模块和项目根资源是否能在干净机器上解析。

建议在空目录或容器中只使用 dist 和计划中的外部依赖做一次真实启动验证,不能仅以构建成功作为部署成功。

二、部署 web 前端

web 端一般通过 Oak CLI 构建:

npm run build:web

或者在预发环境使用:

npm run build:web:staging

这些脚本本质上都来自 oak-cli build --target web --mode ...。构建完成后,再把生成的静态资源发布到你的 web 服务器或 CDN 即可。

需要注意的是,线上 web 前端必须请求真实后端服务。start:web 只是本地 Vite 开发服务,不是生产运行方式。

三、部署小程序、App 和 Desktop

微信小程序和 App 的部署思路与 web 一样,都是“先构建目标端产物,再发布目标端”:

npm run build:mp

React Native 端则还会涉及原生包的打包与签名,这部分更多取决于 React Native 自身的工程流程。

Desktop 先通过 oak-cli add desktop 创建 workspace,再执行生成的构建脚本:

npm run build:desktop:desktop

Tauri 会生成原生 Rust 应用产物,Electron 会交给 electron-builder。Desktop renderer 使用相对 public path,并把 Web 依赖打进本地 bundle,不应依赖在线 CDN 才能启动。发布前还要验证:

  • src/data/i18n.json 已生成并进入原生资源;
  • .oak-desktop.jsonidentifyId 与后端 Desktop Application 配置一致;
  • src/configuration/access.ts 指向真实后端;
  • 安装包签名、自动更新和操作系统权限符合项目发布策略。

但无论是哪一个前端目标端,只要业务逻辑依赖真实数据库、第三方服务、消息推送、定时任务或导入导出能力,线上都必须配套部署 Oak 后端。

四、推荐的上线顺序

一个比较稳妥的上线顺序如下:

  1. 在构建机上执行生成与编译脚本;
  2. 发布后端代码和配置;
  3. 对已有数据库执行并审核 db:upgrade:plan
  4. 首次部署执行 server:init,已有库执行审核后的结构升级 SQL;
  5. 执行权限、i18n、静态数据升级脚本;
  6. 启动新的后端进程;
  7. 再发布前端静态资源或多端包。

如果你的项目已经进入持续发布阶段,还应把数据库变更、静态数据更新和前端发布进一步拆成明确的流水线步骤。Oak 在框架层面已经把“对象定义”“依赖装配”“国际化编译”“服务端运行”这些关键阶段分清楚了,部署脚本只需要老老实实顺着这个顺序来。

五、不要把开发命令直接当成生产命令

最后强调一个很容易被新手忽略的问题:

start:webstart:mp 这类命令只负责目标端开发服务,不是为了替代正式部署。

真正的业务系统仍然需要一个完整运行的 Oak 后端进程来承担一致性、权限、定时、导入导出、外部集成等职责。前端目标端产物只是用户入口,不是业务运行核心。