架构设计
命名规范与平台优先布局
包命名规则、为什么平台优先、shared 层准入标准
平台优先的目录布局
packages/ 顶层按平台切分,跨端共享的纯数据/类型集中在 shared/:
packages/
├── @core/ # 跨端运行时基础
├── shared/ # 跨端纯类型 / tokens(零或极轻依赖)
├── hooks/ # 跨端 React hooks
├── web/ # ← Web 端一整棵
├── native/ # ← Native 端一整棵(预留)
└── miniapp/ # ← 小程序端一整棵(预留)为什么不抽一个「通用 UI 包」
- 每个平台
peerDependencies完全不同(antd / nativewind / Taro),强行抽顶层只是多套一层壳; - 平台目录里除了 UI 还有 theme / tailwind-plugin / materials 等强平台耦合包,单独抽走 UI 会让平台目录「残缺」;
- 真正跨端共享的只有 token 与类型,放
shared/薄包即可。
包命名规则
| 包类别 | 规则 | 示例 |
|---|---|---|
| 跨端共享(纯数据/类型) | 不带平台前缀 | @skyroc/ui-types、@skyroc/ui-tokens |
| Web 端 UI | @skyroc/web-* | @skyroc/web-ui、@skyroc/web-ui-compose、@skyroc/web-ui-antd |
| Web 端主题/工具 | @skyroc/web-* 或保留专名 | @skyroc/web-admin-theme、@skyroc/tailwind-plugin |
| Native 端 | @skyroc/native-* | @skyroc/native-ui、@skyroc/native-theme |
| 小程序端(将来) | @skyroc/miniapp-* | @skyroc/miniapp-ui |
不要起
@skyroc/ui这种「裸名包」——多端并存时无法判断它属于哪一端。
命名与目录的对应
包名和目录名不一定一致,常见的映射:
| 目录 | 包名 |
|---|---|
packages/web/ui/shadcn | @skyroc/web-ui |
packages/web/antd-theme | @skyroc/adapter-antd-theme |
packages/@core/state | @skyroc/core-state |
packages/primitives/filed-form | @skyroc/form |
internal/uno-config | @sa/uno-config |
shared/ 准入规则
shared/* 必须严格保持「零或极轻依赖」:
- ✅ 纯 TS 常量(spacing、colors、radius、fontSize…)
- ✅ 类型定义(
ThemeColor、WithClassName…) - ✅ 极轻量工具(如
clsx) - ❌ React 运行时 / DOM API / React Native API / 任何平台原生模块
- ❌ 大型依赖(antd、tailwindcss 等)
举例:颜色 token(hex / hsl 常量)放 @skyroc/ui-tokens,但颜色 算法(OKLCH 调色板生成)放 @skyroc/color——后者依赖 colord/culori,不符合 shared 准入。
包子入口(exports)约定
很多包用子入口区分「平台无关」和「平台相关」能力:
// @skyroc/utils
{
"exports": {
".": "./src/index.ts", // 平台无关
"./path": "./src/path.ts", // 路径工具
"./web": "./src/web/index.ts" // 仅浏览器(download/openWindow…)
}
}// @skyroc/hooks
{
"exports": {
".": "./src/index.ts", // RN 安全
"./web": "./src/web/index.ts" // useCopy / useSystemTheme + 主出口
}
}这样 Native 端引用 . 不会误打包浏览器 API。