一、什么是Monorepo?

Monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。

二、为什么是Rush?

Rush 是微软开发的可扩展的 Monorepo 工具及解决方案。

工具

Turborepo

Rush

Nx

Lerna

Pnpm Workspace

依赖管理

版本管理

增量构建

插件扩展

云端缓存

Stars

25.5K

5.7K

22.6K

35.5K

28.4K

根据github严选我们选择Lerna + pnpm workspace是最简单安全的方案,但是根据功能的完备性,我们的目标只有一个Rush,尽管Stars的数量不高,但是功能确是最完备的。所以下面我来带大家使用。

三、Rush,启动!

一、初始化一个Rush项目

npx pnpm add -g pnpm // 全局安装 pnpm,已安装pnpm可省略
pnpm install -g @microsoft/rush // 全局安装 rush
mkdir 项目名称
cd 项目名称
rush init

然后我们就看到了我们的基础Rush已经搭建好了项目,然后目录结构大概就是这个样子

二、创建整体项目结构

  1. 直接在目录下创建apps目录来代表自己要控制的子项目目录

  2. 直接创建config目录来统一管理各种项目的config文件

  3. 直接创建packages目录来写通用的公共法方法

然后目录就成了这样

三、整几个项目进去

我们在apps中创建子项目并分别进行npm init -y, 或者直接拖进来一个完整的项目也可以,我们根据需要修改项目名称。然后将路径与名称对应到rush.json中去,给大家看一下自己大文件上传项目成品截图

这是服务端

这是客户端

然后我们打开rush.json文件,增加如下内容

 "projects": [
    {
      // 大文件上传-服务端
      "packageName": "@project/upload-file",
      "projectFolder": "apps/upload-file"
    },
    {
      // 大文件上传-客户端
      "packageName": "@project/upload-file-vue",
      "projectFolder": "apps/upload-file-vue"
    }
  ]

四、原神 Rush,启动!

这时候我们执行

rush update

项目就可以初始化npm 包内的问题了

这时候我们只需要跟往常一样执行项目代码就可以跑起来项目内容了

cd apps/upload-file
npm run dev

cd apps/upload-file-vue
npm run dev

四、实现子项目引用

一、如何实现一套适配的ts-config

我们在config文件夹下增加ts-config文件夹,并npm init -y,修改名称为@config/ts-config后,在运行时依赖增加"typescript": "~5.0.4",然后并分别增加tsconfig.base.json、tsconfig.node.json、tsconfig.web.json、global.d.ts

还是以我的大文件上传项目为参考

下面我们填充这三个JSON文件

tsconfig.base.json

{
  "$schema": "http://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "allowJs": false,
    "allowSyntheticDefaultImports": true,
    "alwaysStrict": true,
    "declaration": true,
    "composite": true,
    "incremental": true,
    "strictNullChecks": true,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "Node10",
    "lib": ["ES2018"],
    "module": "CommonJS",
    "noFallthroughCasesInSwitch": true,
    // 这个普遍反馈会让代码变得啰嗦,暂定遵循原本 bot 的设置,关闭
    "noImplicitReturns": false,
    "removeComments": false,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "strict": true,
    "target": "es2018"
  },
  "watchOptions": {
    "excludeDirectories": [
      "**/node_modules",
      "**/__tests__",
      "**/__coverage__",
      "**/__mocks__",
      "output",
      "dist",
    ]
  }
}

tsconfig.node.json

{
  "$schema": "http://json.schemastore.org/tsconfig",
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
  },
  "ts-node": {
    "files": true
  }
}

tsconfig.web.json

{
  "$schema": "http://json.schemastore.org/tsconfig",
  "extends": "./tsconfig.base.json",
  "files": ["./global.d.ts"],
  "compilerOptions": {
    "declaration": true,
    "jsx": "preserve",
    "lib": ["dom", "dom.iterable", "esnext"]
  }
}

然后我们在打开rush.json文件,增加如下内容

  "projects": [
	...,
    	{
      	// ts-默认配置
      	"packageName": "@config/ts-config",
      	"projectFolder": "config/ts-config"
    	},
	]

然后我们打开我们的apps中的两个项目,并分别进入package.json文件,在开发依赖中增加"@config/ts-config": "workspace:*", 然后我们重新运行

rush update

我们为两个项目分别增加tsconfig.json,内容如下

upload-file/tsconfig.json

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "@config/ts-config/tsconfig.node.json",
  "compilerOptions": {
  },
  "include": ["src"]
}

upload-file-vue/tsconfig.json

{
  "$schema": "https://json.schemastore.org/tsconfig",  
  "extends": "@config/ts-config/tsconfig.web.json",
  "compilerOptions": {
  },
  "include": ["src"]
}

他们分别继承了tsconfig.node.json与tsconfig.web.json

此时此刻我们按住ctrl键可以跳到对应的代码中

如果我们的封装足够好,我们就可以实现整合统一全部TS类型,而又兼顾了应对细小变更的方案

二、根据相同的思路我们还可以实现一套方法库

我们在packages文件夹下增加backend/common/frontend文件夹,分别代表Node独占方法,公共方法,Web独占方法。因为大家都知道,Node可以操作文件,Web可以操作DOM乱引用会导致报错,使用我们需要分开引用。

实现思路与上面操作思路一致,增加项目,标注到rush.json,其他项目进行引用,重新rush update

三、我们要把一个前后端分离项目引用同一个类型文件怎么办?

这时候可能根据上面的思路我们需要单独维护一个独立type类型库,实际上这是不需要的,我们可以将类型放到服务端,并且导出类型,然后我们使用客户端直接引用。我们仍然已大文件上传项目举例子

rush update

然后我们就可以愉快的引用辣!

五、常用rush指令

rush update // 重新跑依赖

rush unlink // 断联依赖

rush purge // 去除node_modules

rush build // 全部打包

六、常见问题

  1. 怎么增加package.json内的依赖?

    1. 手动,没想到吧我是手动现查npm加的,然后直接rush update

  2. 跑不起来怎么办?

    1. 因为依赖问题,你哪怕把rush项目移动到另一个文件夹他就得重新跑

    2. 使用我们先执行rush update

    3. 如果没解决,我们挨个执行rush unlink、rush purge、rush update

    4. 如果还没解决,哥们,检查一下你的rush.json是否正确配置的项目位置与名称

    5. 然后再看看依赖有没有相互引用,不能出现A引用B,B也引用A的代码

七、查看源码

点击查看

未曾清贫难成人,不经打击老天真。 自古英雄出炼狱,从来富贵入凡尘。 醉生梦死谁成气,拓马长枪定乾坤。 挥军千里山河在,立名扬威传后人。