GitNexus Monorepo 是如何维护

文章目录

  • 前言
    • [📦 **Monorepo 结构详解**](#📦 Monorepo 结构详解)
      • [**1. 根目录 package.json 的角色**](#1. 根目录 package.json 的角色)
      • [**2. 子包 package.json 的角色**](#2. 子包 package.json 的角色)
        • [**A. gitnexus/ (CLI + MCP 服务器) --- 唯一发布到 npm 的包**](#A. gitnexus/ (CLI + MCP 服务器) — 唯一发布到 npm 的包)
        • [**B. gitnexus-web/ (React UI) --- 也是私有包**](#B. gitnexus-web/ (React UI) — 也是私有包)
        • [**C. gitnexus-shared/ (共享类型库)**](#C. gitnexus-shared/ (共享类型库))
        • [**D. eval/ (Python 评估框架)**](#D. eval/ (Python 评估框架))
    • [🔗 **依赖链接方式**](#🔗 依赖链接方式)
      • [**"file:" 协议 (本地文件链接)**](#"file:" 协议 (本地文件链接))
    • [📊 **完整依赖图**](#📊 完整依赖图)
    • [🛠️ **日常开发工作流**](#🛠️ 日常开发工作流)
      • [**场景 1:修改 gitnexus-shared 中的类型**](#场景 1:修改 gitnexus-shared 中的类型)
      • [**场景 2:本地运行 CLI**](#场景 2:本地运行 CLI)
      • [**场景 3:本地运行 Web UI**](#场景 3:本地运行 Web UI)
      • [**场景 4:发布新版本到 npm**](#场景 4:发布新版本到 npm)
    • [📋 **Monorepo 和 npm workspaces 的区别**](#📋 Monorepo 和 npm workspaces 的区别)
      • [**GitNexus 的方式(手动链接)**](#GitNexus 的方式(手动链接))
      • [**如果使用 npm workspaces**](#如果使用 npm workspaces)
    • [❓ **常见问题**](#❓ 常见问题)
      • [**Q: 为什么 gitnexus-web 也叫 "gitnexus"?**](#Q: 为什么 gitnexus-web 也叫 "gitnexus"?)
      • [**Q: npm install 时发生了什么?**](#Q: npm install 时发生了什么?)
      • [**Q: 为什么不用 Lerna 或 pnpm?**](#Q: 为什么不用 Lerna 或 pnpm?)
    • [🎯 **总结:这个项目的 Monorepo 策略**](#🎯 总结:这个项目的 Monorepo 策略)

前言


简短回答

不使用 Lerna / pnpm workspace / yarn workspace

而是使用 npm 原生的 workspaces 特性 + 手动依赖链接 (file:../)


📦 Monorepo 结构详解

1. 根目录 package.json 的角色

json 复制代码
{
  "name": "gitnexus-monorepo",    // 标识这是一个 monorepo
  "private": true,                // 🔑 重要:不发布根包到 npm
  "scripts": {
    "format": "prettier --write .",        // 根级全局命令
    "lint": "eslint .",
    "gitnexus:refresh": "gitnexus analyze --embeddings --skills"
  },
  "devDependencies": {
    // 🔑 关键:所有包共享这些开发工具
    "@typescript-eslint/eslint-plugin": "^8.57.2",
    "eslint": "^9.39.4",
    "prettier": "^3.8.0",
    "husky": "^9.1.7",
    "lint-staged": "^15.5.0"
  }
}

作用

  • ✅ 定义整个 monorepo 的 lint/format/prepare 规则
  • ✅ 所有子包都继承这些 devDependencies
  • private: true 确保根包不会被发布到 npm

2. 子包 package.json 的角色

A. gitnexus/ (CLI + MCP 服务器) --- 唯一发布到 npm 的包
json 复制代码
{
  "name": "gitnexus",              // 🔑 这个名字会发布到 npm
  "version": "1.6.5",              // 当前版本
  "private": false,                // ❌ 不设置,默认公开
  "type": "module",                // ESM 模块格式
  "bin": {
    "gitnexus": "dist/cli/index.js" // 🔑 CLI 命令入口
  },
  "files": [
    "dist",     // 只包含编译后的文件
    "hooks",
    "scripts",
    "skills",
    "vendor",
    "web"
  ],
  "dependencies": {
    // 运行时依赖 (用户安装时会下载)
    "@huggingface/transformers": "^4.1.0",
    "@ladybugdb/core": "^0.16.1",
    "tree-sitter": "^0.21.1",
    "express": "^5.2.1",
    // ... 很多其他包
  },
  "devDependencies": {
    "gitnexus-shared": "file:../gitnexus-shared",  // 🔑 本地链接
    "typescript": "^5.4.5"
  }
}

关键特性

  • ✅ 发布到 npm 的唯一包
  • ✅ 包含 bin 字段,定义 CLI 命令
  • "gitnexus-shared": "file:../gitnexus-shared" 表示 本地依赖链接
B. gitnexus-web/ (React UI) --- 也是私有包
json 复制代码
{
  "name": "gitnexus",          // 🔑 注意:和 CLI 同名!
  "private": true,             // 不发布到 npm
  "version": "0.0.0",          // 版本为 0.0.0(不重要)
  "type": "module",
  "dependencies": {
    "react": "^19.2.5",
    "vite": "^8.0.11",
    "gitnexus-shared": "file:../gitnexus-shared",  // 🔑 本地链接
    "sigma": "^3.0.2",         // 图可视化库
    "@langchain/anthropic": "^1.3.29"
  }
}

关键特性

  • ✅ 也依赖 gitnexus-shared(共享类型)
  • ✅ 有自己的构建脚本(Vite)
  • ✅ 私有,不发布
C. gitnexus-shared/ (共享类型库)
json 复制代码
{
  "name": "gitnexus-shared",
  "version": "1.0.0",
  "private": true,             // 私有包
  "type": "module",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",  // 🔑 TypeScript 类型声明入口
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    },
    "./test-helpers": {        // 支持 `import from "gitnexus-shared/test-helpers"`
      "types": "./dist/test-helpers.d.ts",
      "default": "./dist/test-helpers.js"
    }
  },
  "files": [
    "dist",
    "src"
  ],
  "devDependencies": {
    "typescript": "^6.0.3"
  }
}

关键特性

  • ✅ 只包含 TypeScript 类型定义和常量
  • ✅ 导出子路径支持 (exports 字段)
  • ✅ 被 CLI 和 Web 都导入
D. eval/ (Python 评估框架)
js 复制代码
[project]
name = "gitnexus-swebench-eval"
version = "0.1.0"
requires-python = ">=3.11"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

关键特性

  • ✅ 完全独立的 Python 项目 (pyproject.toml)
  • ✅ 不被 npm 管理
  • ✅ 有自己的 Python 依赖

🔗 依赖链接方式

"file:" 协议 (本地文件链接)

这是 npm 的原生特性,不需要任何工具(如 lerna、pnpm):

json 复制代码
// gitnexus/package.json 和 gitnexus-web/package.json 都这样写:
"devDependencies": {
  "gitnexus-shared": "file:../gitnexus-shared"
                     ^^^^^^^^^^^^^^^^^^^^^^
                     相对路径指向本地包
}

工作原理

bash 复制代码
npm install
  ↓
npm 看到 "file:../gitnexus-shared"
  ↓
在本地找到 gitnexus-shared/ 目录
  ↓
符号链接 (symlink) 到 node_modules/
  ↓
导入时:import from "gitnexus-shared" → 使用本地版本

验证

bash 复制代码
cd gitnexus
ls -la node_modules/gitnexus-shared
# lrwxr-xr-x  ... gitnexus-shared -> ../../../gitnexus-shared
                                       ↑
                                    是符号链接!

📊 完整依赖图

js 复制代码
┌──────────────────────────────────────────────────────────┐
│         package.json (根 - 私有)                         │
│  • 共享: prettier, eslint, husky, lint-staged           │
│  • 统一: npm install, npm run format, npm run lint       │
└──────────────────────────────────────────────────────────┘
              ↓                        ↓                    ↓
    ┌─────────────────┐   ┌──────────────────┐   ┌────────────────┐
    │  gitnexus/      │   │ gitnexus-web/    │   │ gitnexus-      │
    │ (CLI 包)        │   │ (Web UI)         │   │ shared/ (types)│
    │                 │   │                  │   │                │
    │ private: false  │   │ private: true    │   │ private: true  │
    │ 发布到 npm ✅   │   │ 内部用 ❌         │   │ 内部用 ❌      │
    │                 │   │                  │   │                │
    │ depends on:     │   │ depends on:      │   │ exports:       │
    │ gitnexus-shared │   │ gitnexus-shared  │   │ • index        │
    │ (file:../...)   │   │ (file:../...)    │   │ • test-helpers│
    └─────────────────┘   └──────────────────┘   └────────────────┘
            ↓                        ↓                    ↑
            └────────────────────────┴────────────────────┘
                  (都用 file: 引用)

            ┌──────────────────────┐
            │ eval/ (Python)       │
            │ pyproject.toml       │
            │ 独立包                │
            │ 不被 npm 管理         │
            └──────────────────────┘

🛠️ 日常开发工作流

场景 1:修改 gitnexus-shared 中的类型

bash 复制代码
# 1. 编辑文件
cd gitnexus-shared
vim src/index.ts

# 2. 构建
npm run build        # 运行 tsc,生成 dist/

# 3. gitnexus 和 gitnexus-web 立即看到新类型
#    因为它们通过 file: 链接指向本地 dist/
#    TypeScript 会自动重新编译

# 4. 不需要 npm publish!

场景 2:本地运行 CLI

bash 复制代码
cd gitnexus

# 开发模式 (tsx watch)
npm run dev
# gitnexus 命令 → src/cli/index.ts

# 或直接运行
npm run build
gitnexus analyze /path/to/repo

场景 3:本地运行 Web UI

bash 复制代码
cd gitnexus-web

# 开发模式 (Vite)
npm run dev
# 打开 http://localhost:5173

# Web UI 通过 axios 调用 gitnexus serve 的 HTTP API
# gitnexus serve 地址: http://localhost:4747

场景 4:发布新版本到 npm

bash 复制代码
# 只有 gitnexus/ 被发布
cd gitnexus

# 1. 更新版本
npm version minor        # 1.6.5 → 1.7.0

# 2. npm 自动构建
npm run prepare          # 因为 package.json 中有 "prepare": "node scripts/build.js"

# 3. 发布
npm publish

# gitnexus-shared 和 gitnexus-web 不发布
# eval/ 是 Python 包,单独管理

📋 Monorepo 和 npm workspaces 的区别

GitNexus 的方式(手动链接)

json 复制代码
// package.json
{
  "devDependencies": {
    "gitnexus-shared": "file:../gitnexus-shared"
  }
}

优点

  • ✅ 简单,无需额外工具
  • ✅ 完全控制发布策略
  • ✅ 子包可以完全独立

缺点

  • ❌ 手动管理依赖版本
  • ❌ 复杂的 monorepo 可能难以维护

如果使用 npm workspaces

json 复制代码
// package.json (假设)
{
  "workspaces": [
    "gitnexus",
    "gitnexus-web",
    "gitnexus-shared"
  ]
}

优点

  • ✅ 自动符号链接
  • ✅ 统一版本管理
  • ✅ 统一 node_modules

缺点

  • ❌ 更复杂的配置
  • ❌ 子包紧耦合

常见问题

Q: 为什么 gitnexus-web 也叫 "gitnexus"?

json 复制代码
// gitnexus/package.json
{ "name": "gitnexus" }      // 发布到 npm

// gitnexus-web/package.json
{ "name": "gitnexus", "private": true }  // 内部用,不冲突

private: true 使其不会发布,所以不会冲突。这样内部引用时可以用同一个名字。

Q: npm install 时发生了什么?

bash 复制代码
npm install
  ↓
npm 看到 root package.json
  ↓
安装 root 的 devDependencies (prettier, eslint 等)
  ↓
找到所有子包的 package.json
  ↓
对每个子包,处理 file: 链接 → symlink 到 node_modules/
  ↓
安装每个子包的 dependencies + devDependencies

Q: 为什么不用 Lerna 或 pnpm?

:因为:

  • GitNexus 只有 3-4 个 npm 包,不复杂
  • 只有 1 个包发布到 npm (gitnexus/)
  • 手动 file: 链接足够
  • 无需额外工具的复杂性

🎯 总结:这个项目的 Monorepo 策略

特性 实现
包数量 4 个 (gitnexus, gitnexus-web, gitnexus-shared, eval)
共享工具 根 package.json 的 devDependencies
依赖链接 "file:../package-name" 协议
发布策略 只有 gitnexus/ 发布到 npm
工具选择 npm 原生,无 lerna/pnpm/yarn
git 策略 单一代码库,原子提交
版本号 gitnexus/ 同步,其他包独立或不发布

这种设计轻量级但有效,适合中等规模的多包项目!

相关推荐
searchforAI1 天前
2026年音视频笔记工具横评:通义听悟、讯飞听见、Get笔记、Ai好记
人工智能·笔记·gpt·aigc·音视频·语音识别·知识图谱
高洁012 天前
知识图谱:AI的超级大脑
人工智能·python·数据挖掘·知识图谱
图特摩斯科技2 天前
AI自动构建本体?安排! Harness+OntoFlow让本体开发像搭积木一样简单
人工智能·知识图谱·abutiongraph·本体论·palantir·ontology
一个数据大开发2 天前
从 Chatbot 到 Agent OS:大模型如何重构企业软件入口
人工智能·知识图谱
大叔_爱编程2 天前
基于职业能力的知识图谱的学习路径推荐系统_django
django·毕业设计·源码·知识图谱·课程设计
空中海4 天前
HarmonyOS知识图谱和回顾
华为·知识图谱·鸿蒙
cookqq5 天前
Palantir Foundry 核心建模体系:构建企业级智能知识图谱的基石
人工智能·机器学习·知识图谱·ai编程
一个数据大开发5 天前
本体论与大模型的融合实践:知识图谱的下一个十年
人工智能·知识图谱
空中海5 天前
Redis知识图谱和回顾
数据库·redis·知识图谱