多平台工作区
当前 Oak 应用把业务源码和平台壳分开组织:src 保存实体、业务逻辑、页面和组件,Web、微信小程序、React Native、Desktop 各自拥有独立 workspace。新应用默认只创建 Web;其它平台在真正需要时通过 oak-cli add 加入。
平台模型
| 平台 | 添加命令 | 构建目标 | 说明 |
|---|---|---|---|
| Web | 默认生成,或 oak-cli add web web2 | web | 浏览器 renderer |
| 微信小程序 | oak-cli add mp wechatMp | mp / wechatMp | Vite 小程序编译与微信产物 |
| React Native | oak-cli add rn native | rn / native | iOS、Android 原生应用 |
| Desktop | oak-cli add desktop desktop | desktop | 默认 Tauri,也支持 Electron |
mp、rn 是命令别名,内部会规范为 wechatMp、native。workspace 名可以自定义,CLI 会把 --subDir 写入对应 npm script;不要在业务代码里假设目录一定叫 wechatMp、native 或 desktop。
添加 workspace 后重新执行:
npm install
npm run make:locale
oak-cli add 会同步依赖、平台 TypeScript 配置和 npm scripts,但不会替你安装刚写入 package.json 的依赖。
Desktop:Tauri 与 Electron
创建 Tauri workspace:
oak-cli add desktop desktop
创建 Electron workspace:
oak-cli add desktop desktop-electron --runtime electron
不传 --runtime 时默认使用 Tauri。生成后会出现类似脚本:
{
"start:desktop:desktop": "oak-cli start --target desktop --render tauri --subDir desktop",
"build:desktop:desktop": "oak-cli build --target desktop --render tauri --subDir desktop"
}
Desktop 是 Web renderer 的一种运行形态:编译时 OAK_PLATFORM 仍为 web,再通过 OAK_RENDER=tauri 或 OAK_RENDER=electron 区分原生壳。oak-general-business 中的应用仍使用 Web Application 类型,并通过 config.render 和 identifyId 区分浏览器、Tauri、Electron。不要创建自定义 desktop AppType。
生成内容
每个 Desktop workspace 都包含 .oak-desktop.json:
{
"schemaVersion": 1,
"runtime": "tauri",
"identifyId": "00000000-0000-4000-8000-000000000000"
}
实际 identifyId 由 CLI 生成并保持稳定。它用于后端匹配对应 Desktop Application,不是用户登录凭证,也不应交给 renderer 业务代码自行修改或伪造。
Tauri workspace 还包含 src-tauri Rust 工程;Electron workspace 包含薄的 main/preload 入口和 electron-builder.yml。两种运行时共用 Desktop 页面、Fluent UI 壳、路由、权限菜单、系统主题和离线 locale 装载方式。
启动与构建
npm run server:start
npm run start:desktop:desktop
Desktop 命令会先启动 Vite renderer,等待端口可访问,再启动 Tauri 或 Electron;任一子进程退出时会清理另一侧。Tauri 使用 tauri.conf.json 的固定 devUrl 端口,默认是 1420;Electron 从指定端口或 1420 开始寻找空闲端口。
生产构建:
npm run build:desktop:desktop
Tauri 构建 renderer 后调用 Tauri CLI;Electron 构建 renderer 后调用 electron-builder。Desktop 产物必须离线可启动,所以生产 renderer 不使用 Web CDN external,React 等运行依赖会进入本地 bundle。
后端访问与离线启动
Web 和 Desktop 都从 src/configuration/access.ts 解析 Oak 后端 URL。不要再从 common.ts 单独派生 Desktop 端口,也不要把第二份后端地址写进 Rust、Electron main 或 CSP。
Desktop 对配置命中的 localhost / 127.0.0.1 Oak 请求使用原生桥接,并注入 renderer 与 application 识别元数据;其它外部 URL 继续使用浏览器 fetch。identifyId 只应在原生边界注入。
Desktop 启动和构建会先生成并复制 src/data/i18n.json。Tauri 把它嵌入资源,Electron 把它打进应用包;Locales feature 会把离线数据同步进正常 Cache。缺少该文件时,先执行:
npm run make:locale
应用解析还可以保存并回放已验证的 Application 查询快照,在真实网络异常时支持离线启动;普通业务查询不会因此自动变成离线数据库。
Desktop render 选择
普通模块选择顺序以 Desktop 和操作系统入口优先,然后回退到 Web:
.desktop.* -> .windows|.macos|.linux.* -> .web.* -> 普通入口
Oak 页面和组件 render 的回退顺序是:
render.desktop.tsx
render.windows.tsx / render.macos.tsx / render.linux.tsx
web.pc.tsx
web.tsx
共享组件通常不需要专门写 Desktop render;只有桌面交互确实不同才增加 render.desktop.tsx 或操作系统入口。
微信小程序 workspace
oak-cli add mp wechatMp
npm install
npm run start:mp:wechatMp
当前 Vite 小程序构建会根据页面配置生成 canonical route map。业务导航应使用 Oak navigator 的 /namespace/page 逻辑路径;静态的 wx.navigateTo、redirectTo、reLaunch、switchTab URL 也会尝试在构建时改写。不要手写 /pages/.../index 或分包产物路径。
switchTab 不能携带 query 或 state。动态拼接且无法静态识别的路径会产生 warning,应改为 Oak navigator 或明确的静态路由。
小程序还支持:
index.config.ts生成页面/组件 JSON;- XML/WXML 表达式、事件、properties 和 class 类型检查;
- 分包与独立分包 chunk、asset、WXS/i18n 输出;
- 构建产物图片压缩和 Node polyfill 白名单;
- bundle treemap、分包统计和反向依赖图。
这些编译选项见编译与构建配置。
React Native workspace
oak-cli add rn native
npm install
npm run start:native:native
npm run run:android:native
iOS 使用 run:ios:<workspace>。Metro 只负责 JavaScript 开发服务,原生 SDK、签名、证书和渠道包仍由 React Native、Android Studio 和 Xcode 工程管理。
当前 workspace 同时生成生产构建脚本:
npm run build:native:native:android
npm run build:native:native:ios
Android 命令会继续进入原生依赖 codegen、Metro bundle 与 Gradle release 构建;没有配置 ANDROID_HOME 或 native/android/local.properties 时会在 SDK 检查处失败。不要把 local.properties、keystore、签名密码或渠道凭证提交到仓库。
页面/组件优先使用 render.native.tsx 与 render.native.scss,需要平台差异时再增加 render.ios.tsx 或 render.android.tsx。
多 workspace 注意事项
- locale、router、alias 和 TypeScript 配置根据 npm scripts 中的
--target、--subDir发现 workspace,不应硬编码默认目录。 - 新 workspace 使用自己的
tsconfig.json;根配置主要负责共享源码和编辑器聚合。 oak-cli add --from <dir>会复制一个完整 workspace,不再覆盖内置平台 scaffold;传入目录必须自己满足目标运行时合同。- 页面、菜单、route access 和 namespace config 仍来自共享
src/pages/**/index.config.ts,平台 workspace 消费生成结果,不应在运行时重新扫描源码。