架构设计

平台优先目录

packages/web / packages/native / packages/hooks / packages/primitives 的分工与共生

定位

「平台优先」(Platform-first) 是本仓库的核心目录策略:

包不按「类型」(components / hooks / utils)组织,而按「平台」(web / native / miniapp / @core / primitives)组织。

这意味着:当你打开 packages/web/ 你看到的全部都是 Web 专属代码;打开 packages/@core/ 看到的全部都是跨平台代码。目录就是承诺

平台目录

packages/
├── @core/         # 跨平台 · 无 UI · 业务核心能力
├── hooks/         # 跨平台 · React hooks
├── primitives/    # 跨平台 · UI-agnostic 能力原语
├── web/           # Web 专属(DOM / antd / vite)
│   └── ui/        # Web 设计系统组件
├── native/        # React Native 专属
│   └── ui/        # RN 设计系统组件
└── miniapp/       # 小程序专属(预留)
    └── ui/        # 小程序组件

前三个是跨平台的,后三个是平台专属的。各目录下具体有哪些包、分别叫什么,见 目录结构总览

1. @core/ —— 跨平台无 UI 业务核心

性质含义
平台无关不引用 DOM、不引用 RN API
无 UI不包含组件、不输出 DOM/JSX
业务相关是项目长期沉淀的领域能力
适配器平台差异通过 Adapter Pattern 注入

包(9 个):typesutilscoloraxiosstateloggerservicetailwind-pluginscripts

详见 跨端核心总览

2. hooks/ —— 跨平台 React hooks

性质含义
跨端Web、RN、小程序都可用
React 运行时依赖 React,因此不放进 @core/
平台子入口浏览器专用 hooks 隔离在 ./web

包(1 个):@skyroc/hooks

这里曾经还有一个 shared/ 目录,放 @skyroc/ui-types@skyroc/type-utils 两个纯类型包。 为几十行类型单开一个包要长期付版本、构建与发布的成本,它们已分别并入 @skyroc/utils/type@skyroc/tailwind-plugin/uishared/ 目录已删除。

详见 跨端共享层@skyroc/hooks

3. primitives/ —— UI-agnostic 能力原语

性质含义
跨端不绑定渲染层
能力解决一类问题(form / router / media)
无样式不提供视觉,由消费方组合

包:filed-form(即 @skyroc/form,类型安全的表单原语)。后续会有 router / media / dnd 等。

4. web/ —— Web 专属

子目录性质
tailwind-pluginantd-theme设计系统基础
materials骨架结构组件
ui/(shadcn / antd / compose)设计系统层
admin-themeadmin-i18nadmin-layoutsadmin-notificationadmin-runtimeadmin-stylesadmin-viteadmin/devtoolsAdmin 应用层

详见 Web 端包总览

5. native/ —— React Native 专属

包含 RN 专用 UI 与平台适配,依赖 @core/* 提供业务能力。

6. miniapp/ —— 小程序专属

预留目录,与上面同构。

为什么这样切

替代方案缺陷
按类型切分(components/hooks/utils/跨平台代码与平台特定代码混居,无法按平台 tree-shake
单一 universal 包bundle 必然带上跨平台代码,体积膨胀
复制粘贴到每个端业务逻辑漂移,维护噩梦
condition 字段(browser/react-native)类型推断脆弱,调试困难

平台优先 + Adapter Pattern 的组合让:

  • Web 项目只引 @skyroc/web-* + @skyroc/@core-* + @skyroc/shared-*
  • RN 项目只引 @skyroc/native-* + @skyroc/@core-* + @skyroc/shared-*
  • 业务核心代码只写一份在 @core
  • 平台差异(存储 / fetch / push)通过适配器在端层注入。

依赖方向

平台依赖必须单向

@core  ←  shared  ←  primitives
  ↑          ↑          ↑
  └──────────┴──────────┘

             ├── web/*    (只能往左依赖)
             ├── native/* (只能往左依赖)
             └── miniapp/*(只能往左依赖)
不允许的依赖为何
@core/* 依赖 web/*core 应保持跨平台,不能绑死端
shared/* 依赖 web/*同上
web/* 依赖 native/*(或反之)平台间互不依赖

具体可视化关系见 依赖图

包命名与目录的映射

目录前缀 ≈ 包名前缀web/<name>@skyroc/web-<name>),完整规则表见 命名规范

跨平台代码的常见做法

场景做法
类型 / 常量 / 数据shared/,零依赖
业务核心逻辑(无 DOM)@core/
平台差异(存储 / fetch)@core/ 暴露抽象,端项目注入实现
同名 Hook 跨平台行为不同@skyroc/hooks 主入口(RN 安全)+ ./web 子入口(DOM-only)
同名组件不共用,分别建 web/ui/*native/ui/*

与包分层、适配器模式的关系

  • 包分层 回答:抽象 → 实现 的纵向层级是什么?
  • 平台优先(本页)回答:横向上 Web / RN / 小程序如何分目录?
  • 适配器模式 回答:平台差异如何不污染核心?

三者组合是项目的架构脊柱。

Last updated on