从命名、目录、tsconfig、构建、导出到接入仓库的全流程清单
要建一个新包
│
├── 它只是一组纯类型?
│ └── 不要新建包,并入已有归属:
│ 通用工具类型 → @skyroc/utils/type
│ 设计令牌 / 组件词汇 → @skyroc/tailwind-plugin
│ 全局命名空间声明 → @skyroc/types
│
├── 它跨多个平台、是无 UI 的运行时能力(请求 / 状态 / 日志 / 工具)?
│ └── packages/@core/
│
├── 它跨多个平台、是 React Hook?
│ └── packages/hooks(包已存在,直接加 module)
│
├── 它跨多个平台、是「能力原语」(form、router、media)?
│ └── packages/primitives/
│
├── 它是 Web 专属(DOM / antd / radix / vite plugin / tailwind)?
│ └── packages/web/ 或 packages/web/ui/
│
├── 它是 RN 专属?
│ └── packages/native/
│
├── 它是无 UI 的核心能力(utils / state / service / logger)?
│ └── packages/@core/
│
└── 它是不发布的内部配置(tsconfig / oxlint)?
└── internal/目录定了,包名也就定了——新包一律用 @skyroc/ scope,目录到包名的映射规则见 命名规范。
packages/<group>/<name>/
├── src/
│ ├── index.ts # 主入口
│ ├── <子模块>/
│ └── types/
├── __tests__/ # vitest 测试
├── package.json
├── tsconfig.json
├── tsdown.config.ts # 库构建
├── vitest.config.ts # 可选
├── README.md
└── .oxlintrc.json # 可选(特殊规则)package.json{
"name": "@skyroc/<name>",
"version": "0.0.1",
"private": false,
"description": "...",
"type": "module",
"main": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": ["dist", "README.md"],
"sideEffects": false,
"exports": {
".": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" },
"./package.json": "./package.json"
},
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"clean": "rimraf dist .turbo",
"lint": "oxlint",
"test": "vitest run",
"typecheck": "tsc --noEmit --skipLibCheck"
},
"dependencies": {
"@skyroc/utils": "workspace:*"
},
"devDependencies": {
"@skyroc/config": "workspace:*",
"@skyroc/tsconfig": "workspace:*",
"tsdown": "catalog:dev",
"rimraf": "catalog:dev",
"typescript": "catalog:core",
"vitest": "catalog:dev",
"oxlint": "catalog:dev"
},
"publishConfig": {
"access": "public"
}
}要点:
workspace:* 引用内部依赖;catalog:<group>(Catalog 体系);sideEffects: false(有 CSS 改为数组);publishConfig.access: "public";private: true 并去掉 publishConfig。tsconfig.json| 包类型 | extends |
|---|---|
| 跨平台库 | @skyroc/tsconfig/library.json |
| Web 库 | @skyroc/tsconfig/web.json |
| Node 工具 | @skyroc/tsconfig/node.json |
| RN 库 | @skyroc/tsconfig/react-native.json |
| Web 应用 | @skyroc/tsconfig/web-app.json |
| RN 应用 | @skyroc/tsconfig/react-native-app.json |
{
"extends": "@skyroc/tsconfig/library.json",
"include": ["src", "__tests__"]
}tsdown.config.tsimport { defineConfig } from 'tsdown';
export default defineConfig({
entry: {
index: 'src/index.ts'
},
format: ['esm'],
dts: true,
clean: true,
external: [/^node:/, /^@skyroc\//, 'react', 'react-dom']
});多子入口时:
entry: {
index: 'src/index.ts',
utils: 'src/utils/index.ts',
web: 'src/web/index.ts' // 平台分支
}记得同步更新 package.json 的 exports(Exports 策略)。
.oxlintrc.json(可选)如无特殊规则可省略,全仓继承根 .oxlintrc.json。
React 库通常需要:
{
"extends": ["../../../internal/config/oxlint/react.json"]
}vitest.config.ts(如有测试)import { defineConfig } from 'vitest/config';
import { baseCoverageConfig, baseTestConfig } from '@skyroc/config/vitest';
export default defineConfig({
test: {
...baseTestConfig,
coverage: { ...baseCoverageConfig }
}
});并在 __tests__/ 下加 *.test.ts。
README.md至少包含:
pnpm add @skyroc/<name>;按 开发约定 编写:
useCallback;pnpm-workspace.yaml 中已经覆盖了所有目录,不需要新增 glob。只需:
pnpm installpnpm 会自动检测新包。
# 单包构建
pnpm --filter @skyroc/<name> build
# watch(开发)
pnpm --filter @skyroc/<name> dev在 apps/admin 或 apps/web-ui-playground 中:
// 该应用的 package.json
"dependencies": {
"@skyroc/<name>": "workspace:*"
}再 pnpm install,然后业务里 import { foo } from '@skyroc/<name>'。
pnpm typecheck 通过;pnpm --filter @skyroc/<name> build 通过;pnpm --filter @skyroc/<name> test 通过;pnpm lint 通过;dist/ 文件齐全(每个 entry 都有 .mjs + .d.mts);import 验证;pnpm format 跑过;feat(<name>): scaffold @skyroc/<name>。如果包是公开发布的(@skyroc 公开包):
# 1. 更新版本(手工或 sa release)
pnpm --filter @skyroc/<name> exec npm version patch
# 2. 构建
pnpm --filter @skyroc/<name> build
# 3. 发布
pnpm --filter @skyroc/<name> publish --access public或集成到 sa release 流程,由 Git 提交与发版 描述。
Last updated on