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

背景

公司从 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。

总结

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

相关推荐
徐小夕2 分钟前
JitKnow AI知识库 4.7 发布|多文档推理+拖拽 Agent + 技能库,打造更懂业务的 AI 知识中台
前端·vue.js·github
小poop33 分钟前
从“雷峰塔”到“对象”:JavaScript基础语法入门指南
前端·javascript
ReStock活库35 分钟前
Zephyr异步SPI调用返回后,为什么不能立即复用发送缓冲区?
java·前端·网络
计算机魔术师43 分钟前
半年营收163亿,算力债却到7800亿,这账谁算得清
前端
chunyublog1 小时前
HDFS 上传文件名空格问题排障教程
前端·javascript·npm
?abc!1 小时前
(贪心)621. 任务调度器
java·前端·c#
摸鱼仙人~2 小时前
校招帮简历字段匹配架构分析报告
java·前端·架构
陈随易2 小时前
副业搞钱点子之赛事与活动
前端·后端·程序员
电梯界知识分子2 小时前
景德镇老房重新设计阶段规划楼梯与电梯,1.7m×1.6m空间装400kg观光电梯,棕色框架茶色玻璃适配中式装修
大数据·服务器·前端·网络·家用电梯
Shell运维手记2 小时前
Shell 脚本入门课堂讲解
前端·chrome