多项目解决方案介绍
- npm发包: 将模块代码发布成npm包,用户只需要安装即可使用。
- git submodule/subTree(推荐使用subtree):这种代码架构就是一个主仓库下面有一个或者多个独立仓库,子模块和主模块都有自己的仓库和分支。不同的是git subtree实现了双向修改数据,submodule只能在子模块修改数据,更新后需要提交到主项目。
模块联邦
: 是一种基于webpack5的架构模式,模块联邦通过webpack的ModuleFederationPlugin插件实现,每个模块都是一个单独的构建,这些构建被编译为容器。容器可以异步公开模块,允许构建将每个公开的模块及其依赖项放在单独的文件中,从而减少请求和下载量,提高Web性能。turborepo
: 是一种基于monorepo的构建系统,它能够组织多项目的构建流程,以及使用本地缓存或远程缓存来加快构建速度等。
什么是monorepo?
monorepo(单一代码库):把所有项目的代码统一维护在单一代码库中。这些项目虽然可能相关,但是在逻辑上是独立的,并由不同的团队来维护。
多代码仓库(multirepos): 每个项目存储在一个完全独立的版本库中,这是公司普遍使用的一种方式,比如每个项目的web项目是一个代码库,h5项目是另外一个。
目前,antd,umijs,vant,element ui等开源软件,都是采用monorepo的方式组织项目代码。
monorepo的优点:
1,可见性:每个人都可以看到其他人的代码,对于团队开发比较友好,每个人都可去修复bug.
2, 一致性:把所有的代码放在一起,可以执行的代码质量标准和统一风格更容易。
3,共享时间线:某一共享项目或者api变更会立刻暴露出来,团队可以快速跟进变化。
4,共享性,不同项目使用的相同部分可以抽离出一个单独项目,供其他项目复用。
5,原子提交:开发人员可以一次行提交多个项目。
6,对于微前端项目更友好。
monorepo的缺点:
1,性能差:由于所有项目都放在一起,导致ide或者命令运行比较缓慢。
2,破坏性:某一修改可能会影响全局,如果没有经过严格测试可能会造成多个项目出现bug.
3,学习曲线:增加学习成本。
4,权限控制;失去按项目控制权限。
5,codereview:多个项目同时修改,会增加代码审查难度。
monerepo的实现工具: yarn/pnpm nx turborepo lerna等等。
turborepo简介
turboRepo是一个js和ts的代码构建系统,他是为扩展单包而设计的,同时也使单包工作区的工作流更快。 turoRepo不负责各个工作区的包管理。
如下是monorepo的构建方式:
每个工作共建有它自己的测试,代码检查,构建等,每个任务的执行都是串行的,当很多任务要去执行的时候,这样的做法是非常减速的。而我们需要快速的构建检查等,这样开发人员才能快速交付高质量的代码。
turorepo通过任务并行运行,以及缓存等解决了以上的问题。
turboRepo主要有两个功能:
- 管理工作流,能够配置工作任务的相互依赖关系,实现不同任务的前后运行顺序,且能够实现不同工作区任务流的并行运行
- 缓存输出内容,turborepo能够缓存构建产物(本地缓存和远程缓存),实现两次相同内容的构建只会运行一次。
turborepo学习
1,构建存储库
1,新建一个turborepo项目
使用如下命令可以快速开始构建一个turborepo项目。
npx create-turbo@latest
此应用包括两个应用程序和三个共享库。
声明包的目录:
应用程序会根据包目录查找对应的json文件,每一个json文件对应一个包。
根package.json是工作空间的基础:
根turbo.json配置文件会配置turbo的行为。
使用如下命令可以查看使用turboRepo的示例。
npx create-turbo@latest --example [example-name]
案例名称可以参照如下文档:
** 2,添加TurboRepo到已有的存储库**
可以在任何存储库(单包或者多包)中增量添加使用turboRepo。
添加命令如下:
1,在存储库中项目中安装turbo包
npm install turbo --save-dev
2,添加turbo.json配置turbo的行为
---turbo.json file
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"check-types": {
"dependsOn": ["^check-types"]
},
"dev": {
"persistent": true,
"cache": false
}
}
}
3,编辑.gitignore文件
---.gitignore.file
.turbo
4,运行build和check-types 任务
turbo build check-types
5,在不对代码做任何改变的情况下,再次运行步骤4中的命令
可以看到任务已经被缓存,而不是重新构建。
6,运行 在多包工作空间中,可以使用如下命令去开启所有的任务执行
turbo dev
也可以添加filter指令来只对特定的包进行处理
turbo dev --filter=packageName
2,管理依赖
当我们为对应的包安装依赖的时候,我们应该将依赖包直接安装到使用它的包中。每个包中的package.json中将包含它们所有的依赖项。
包管理器可能会选用与包不同位置的node_modules,也就是monorepo中所有的依赖都会储存在根目录下的 node_modules 中:/monorepo/node_modules
如下是給对应包安装所需依赖的命令:
yarn workspace web add jest --dev
yarn workspace @repo/ui add jest --dev
批量给对应包添加依赖:
yarn workspaces foreach -R --from '{web,@repo/ui}' add jest --dev
但某些情况下,我们可能需要同一 package 的不同版本。例如:一个 react 项目较老,使用 bootstrap 4。而另一个在开发中的新项目决定使用 bootstrap 5。我们可以在packages.json中配置nohist配置。
{
"name": "monorepo",
"version": "1.0.0",
"license": "MIT",
"private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/bootstrap"
]
}
}
3,创建内部包
1,创建一个空文件夹
2,在文件夹下面建立package.json配置文件,使用npm init创建即可。
3,添加tsconfig.json配置文件
- extends可以让你从别的包中继承基础配置
- compilerOptions outDir它制定编译后的结果放在哪里,与package.json中的exports匹配。
- compilerOptions roodi确保outDir的目录和src所在目录一致。
- 创建src文件夹,并在src目录下创建两个文件
- 在应用程序中使用新包
6. 编辑turbo.json文件:
7,运行turo build执行构建任务,再次运行运用,可以看到由于缓存作用,应用可以在毫秒级快速构建完成。
4,配置任务
通过对turbo.json的配置,可以使我们的构建流程更快。
比如之前运行命令执行任务时,cpu的执行状态可能如下:
通过配置turbo.json之后,运行流程如下:
和明显,第二张图片所用到的时间要比第一个少很多,这就是turboRepo的魅力之处。
在turbo.json文件中,使用tasks来配置不同的任务。
dependsOn用于指定当前的任务执行之前必须运行完成的任务。这就是构建依赖,被依赖的项目会优先执行于依赖的项目。
^
语法告诉turoRepo从依赖关系图的底部开始运行.比如A依赖于b的,那么b的build任务将会优先执行,然后a的build任务次才会执行。
有时候可能需要同一个包中的两个任务以特定的顺序执行,比如想执行完build之后执行test任务,那么就可以不带
^
output会让turbo缓存对应的输出文件,这样两次同样的任务将会只执行一次构建任务即可。
input
关键字可以配置对应任务执行的扫描文件,默人情况下,turorepo将会包含所有git追踪的文件。上述配置完成之后,只有对应的markdown文件改变,才会去执行spell-check
任务。
cache可以定义任务是否需要缓存,有些任务无论如何都需要执行,那么就可以将cache
属性置为false.
5,运行任务
在package.json中定义可执行任务的脚本。
6,缓存
6-1本地缓存
利用缓存的时候需要注意,turboRepo假设每个任务的输出和输入是一一对应的,如果同样的输入,但是却会产生不同的输入,那么是不能够使用缓存的。
可以通过以下3个方式来尝试使用缓存:
1,创建一个turboRepo项目
npx create-turbo@latest
2,运行构建脚本
yarn run build
3.再次运行步骤2中的脚本命令,输出结果如下:
可以看到第二次并没有重新构建,因为输入标识可以在缓存中找到,turborepo可以直接从缓存中拿到构建结果,从而节约资源和时间。
6-2远程缓存
Turborepo将任务的结果存储在机器上的.turbo/cache目录中。但是,通过与您的团队成员和CI共享此缓存,您可以使整个组织更快。
使用远程缓存步骤:
1,是用身份验证
npx turbo login
2,将机器的存储库和远程存储库链接起来
npx turbo link
配置完成之后,turorepo会自动将构建输出发送到远程缓存,如果有团队成员在另外一台机器上运行相同的任务,并且该机器也对远程缓存进行了身份验证,那么第一次执行该任务的时候,就会直接从远程缓存拿到对应的构建结果,而不是重新构建。
默人情况下,turbo使用默人配置的vercel远程缓存。你也可以根据文档来配置不同的远程缓存。