代码共享方案-多仓库合并单仓库

背景

公司从 2019 年立项以来,陆续分别开了若干个工程,这里代称为 apple, peach, banana, 以及 infra 工程,每个工程对应公司的一块业务,大体都是不相似的,其中 infra 的工程用于工程间代码共享,其中也有工程依赖于另外的工程,现需要将以上工程中部分功能挪到另一个新开的工程 dashboard。如何将多个仓库融合在一个仓库中,并保留原有历史记录,并且随着业务的演进,能够实时同步代码,且工程大多开发了5年以上,代码量巨大,如何组织代码,本文就是为这一方案而生。

原有工程结构如下:

每个工程都是一个独立的 git 仓库,每个仓库中都有一个 infra submodule 子工程

.gitsubmodules 文件内容

git 仓库调整

通过引用 naraku 这个 shell 工程, 将所有仓库包揽在 naraku 仓库之下,改造完成后工程结构如下:

单体工程改造

webpack 调整

这里以 vue-cli 为例,chainWebpack 中加入以下代码

js 复制代码
{
    chainWebpack: config => {
    // 配置路径别名
    config.resolve.alias
      .set('@', resolve('src'))
      .set('&', resolve('../infra/src'))
  }
}

tsconfig.json 调整

json 复制代码
{
  "extends": "../../tsconfig.common.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
        "&/*": [
            "../infra/src/*"
        ],
        "@/*": [
            "src/*"
        ]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx",
    "../frontend-infra/src/**/*.ts",
    "../frontend-infra/src/**/*.tsx",
    "../frontend-infra/src/**/*.vue",
    "../frontend-infra/src/**/*.ts",
    "../frontend-infra/src/**/*.tsx"
  ]
}

多仓库管理 workspaces 改造

naraku 最外层 package.json 指定 workspaces

json 复制代码
{
  "name": "naraku",
  "version": "1.0.0",
  "description": "",
  "private": true, // 一定要指定为私有仓库
  "workspaces": [ // 指定子仓库的 glob 路径
    "apps/*"
  ],
  "main": "index.js",
  "scripts": {
    "alias": "cross-env APP_NAME=${APP_NAME} node script.js run",
    "bundle": "yarn alias bundle",
    "publishBundle": "yarn alias publishBundle"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^24.3.0",
    "@types/webpack-env": "^1.18.8"
  },
  "dependencies": {
    "commander": "^9.5.0",
    "cross-env": "7.0.3",
    "shelljs": "^0.8.5"
  }
}

启动工程

bash 复制代码
yarn workspace apple run start | build

cicd 改造

通过以上改造之后,单体工程无法单独启动,需要改造通过 naraku 这个 shell 工程启动,构建,我这里是通过在jenkins pipeline 中指定环境变量,来启动不同的工程。

为使用构建需要 ,改造了npm script,所有命令通过 yarn alias 转发, 在根目录新建 script.js

js 复制代码
const { Command } = require('commander');
const shelljs = require('shelljs');
const program = new Command();
const path = require('path');

program
  .name('workspace-alias')
  .description('CLI to turn APP_NAME to package.json name utilities')
  .version('1.0.0');

const workspaceMap = generatedAliasMap()
program.command('run')
  .description('Working with APP_NAME to workspace alias')
  .helpOption('-e, --HELP', 'read more information')
  .argument('<string...>', 'e.g. "build" or "start"')
  .option('-w, --workspace <type>', 'workspace: ' + Object.keys(workspaceMap).join(' | '), process.env.APP_NAME)
  .option('-v, --verbose [type]', 'verbose mode, just ouput the shell going to run', false)
  .action((actions, opts) => {
    // 映射目录 与 workspace
    const workspace = workspaceMap[opts.workspace]
    if (!workspace) {
      console.error(`Workspace alias for "${opts.workspace}" not found!`)
      process.exit(1)
    }

    const script =`yarn workspace ${workspace} ${actions.join(' ')}`
    if (opts.verbose) {
      greenLog(script)
      return
    }

    greenLog(script);
    shelljs.exec(script);
  });

program.parse();

function generatedAliasMap () {
  const apps = shelljs.ls('-d', 'apps/*/')
  const aliasMap = apps.reduce((acc, appPath) => {
    const pkg = require(`./${appPath}/package.json`)
    acc[path.basename(appPath)] = pkg.name
    return acc
  }, {})
  return aliasMap
}

function greenLog (msg) {
  console.log('\x1B[32m%s\x1B[0m', msg)
}

启动工程

bash 复制代码
# yarn alias [action] -w [app_path]
yarn alias start -w infra

优缺点

优点

  1. 通过以上改造实现了保留单体 git 记录。
  2. 随着业务的演进,能够实时同步代码。
  3. 工程改造量较小。
  4. 易于branch 分支管理。

缺点

  1. 单体仓库无法启动。
  2. 单体仓库的改动可能导致 dashboard 无法正常 work。

总结

都看到这里了,如果你有更多好的建议,欢迎在评论区留言。

相关推荐
浏览器工程师35 分钟前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆37 分钟前
VSCode自动格式化三要素
前端
爱勇宝1 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen2 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518134 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode4 小时前
Redis 在生产项目的使用
前端·后端
LiaCode4 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战4 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
风骏时光牛马5 小时前
# Ruby基于Rails框架实现多角色权限管理与数据分页查询完整实战代码案例
前端
weedsfly5 小时前
迭代器、生成器与异步迭代——让数据“按需流动”的艺术
前端·javascript