
在过去的几年中,
单一存储库的概念
已成功确立,因为它可以大大简化开发模块化软件项目(例如基于微服务的基础结构)的过程。 这种架构方法的主要优点在实践中显而易见,因此,我建议从头开始创建自己的测试
单一存储库 ,同时了解使用
纱线工作区和
lerna的细微差别。 好吧,让我们开始吧!
考虑我们项目的结构,这将是位于
packages /文件夹中的三个库以及根目录中的
package.json 。
├── package.json └── packages ├── app │ ├── index.js │ └── package.json ├── first │ ├── index.js │ └── package.json └── second ├── index.js └── package.json
可以理解,我们有两个独立的库
first和
second ,还有一个
应用程序库,它将从前两个库导入函数。 为了方便起见,将所有三个软件包都放在
packages目录中。 您可以将它们保留在根文件夹中,也可以将其放置在任何其他名称的目录中,但是为了遵循普遍接受的约定,我们将以这种方式放置它们。
为了简化实验,
第一个库和
第二个库在
index.js中仅包含一个函数,每个函数都代表模块返回一个hello字符串。 对于第
一个示例,它将如下所示:
在
应用程序模块中,我们将在控制台中显示
来自应用程序的消息
Hi ,以及来自其他两个软件包的问候:
为了使
第一个和
第二个在
应用程序中可用,我们将它们表示为依赖项中的
依赖项 。
另外,对于每个库,我们在包的主要名称前面的值
名称中将前缀
@ monorepo /添加到本地
package.json 。
为什么在软件包名称npm(@ monorepo /)前面需要带有狗形图标的前缀?添加前缀是可选的,但这恰恰是许多单一存储库遵循
的软件包命名
约定 :
babel ,
材质ui ,
角等。 事实是,每个用户或组织在
npm网站上都有自己的
作用域 ,因此可以保证所有带有
@ somescope / postfix的模块都是由
somescope团队创建的,而不是由攻击者创建的。 此外,可以调用已使用的模块名称。 例如,您不能仅仅采用并创建自己的
utils模块,因为这样的库
已经存在 。 但是,添加后缀
@ myscopename /我们可以与二十一点和年轻女士一起获得utils(
@ myscopename / utils )。
对于我们的测试项目,现实生活中的类似物可以是用于处理数据,验证工具,分析或仅一组UI组件的各种库。 如果我们假设要开发一个
Web和
移动应用程序(例如,分别使用
React和
React Native ),并且我们拥有重用逻辑的一部分,那么可能值得将其放入单独的组件中,以供以后在其他项目中使用。 将其添加到
Node.js上的服务器,您将获得一个真实的案例。
纱线工作区
创建完整的mono-
存储库之前的最后
一步是在存储库根目录中设计
package.json 。 注意
工作空间属性-我们指定了
packages / *的值,这意味着“
packages文件夹中的所有子项”。 在我们的例子中,这是
app ,
第一 ,
第二 。
另外,必须在
package.json中指定
“ private”:true ,因为
工作空间仅在私有项目中可用。
为了使一切顺利,请从根目录中执行
yarn命令(类似于
yarn install或
npm install )。 实际上,由于
app模块中存在的依赖项被定义为根
package.json中的 工作区 ,因此,我们不会从
npm-registry下载任何内容,而只是绑定(“链接”)我们的包。
yarn

现在我们可以执行
node命令
。 从根目录运行,该根目录将从
packages / app / index.js文件运行脚本。
node .

让我们看看它是如何工作的。
通过调用
yarn ,我们在
node_modules中创建了
指向 packages文件夹中目录的符号链接。

由于依赖关系之间的关系,我们获得了一个很大的优势-现在,当在第
一个和
第二个模块中进行更改时,我们的
应用程序将收到这些程序包的当前版本,而无需重建。 实际上,这非常方便,因为 我们可以进行软件包的本地开发,但仍将它们定义为第三方依赖项(它们最终将成为第三方依赖项)。
从
纱线工作区获得的下一个重要优点是存储第三方依赖项的组织。
了解有关在顶层存储依赖项的更多信息。假设我们要在
第一和
第二个中使用
lodash库。
通过从适当的目录中
执行yarn add lodash命令 ,我们将收到对本地
package.json的更新-软件包的当前版本将显示在
dependencies中 。
"dependencies": { "lodash": "^4.17.11" }
至于
lodash软件包
本身 -实际上,该库将在根级别一次安装在
node_modules中。
如果外部软件包的所需版本(在我们的示例中为
lodash )在
第一和第二个不同(例如,
首先您需要
lodash v3.0.0 ,在
第二个v4.0.0中 ),则具有较低版本(
3.0.0 )的软件包将到达根
node_modules ,
第二个模块的
lodash版本将存储在本地
包/ second / node_modules中 。
除了优点之外,该方法还可以具有较小的缺点,该
纱线允许在附加标志的帮助下绕过
纱线 。 您可以在
官方文档中了解有关此类细微差别的更多信息。
添加莱娜
使用
lerna的第一步是安装软件包。 通常,他们执行全局安装(
yarn global add lerna或
npm i -g lerna ),但是如果不确定是否要使用此库,则可以使用
npx进行调用。
我们将从根目录初始化
lerna :
lerna init

实际上,我们借助一个命令一次执行了多个操作:创建了一个git存储库(如果之前未初始化过),创建了
lerna.json文件并更新了根
package.json 。
现在,在新创建的
lerna.json文件中
,添加两行-
“ npmClient”:“ yarn”和
“ useWorkspaces”:true 。 最后一行说我们已经在使用
yarn工作区 ,不需要创建
app / node_modules文件夹,其中有指向
第一个和
第二个的符号链接。
Lerna测试
为了显示使用
lerna的便利性,
请为我们的库添加测试。
从根目录,我们安装用于测试的软件包
-jest 。 运行命令:
yarn add -DW jest
为什么需要-DW标志?需要-D(-dev)标志,以便将jest软件包作为dev依赖项安装,而-W标志(-ignore-workspace-root-check)允许在根级别进行安装(这是我们需要的)。
下一步是将一个测试文件添加到我们的软件包中。 为了方便我们的示例,我们将使所有测试相似。 对于第
一个示例,测试文件将如下所示:
我们还需要添加一个脚本来在每个库的
package.json中运行测试:
最后
一步是更新根
package.json 。 添加一个
测试脚本,该脚本将调用
lerna run test --stream 。
lerna run之后的参数定义了将在
package /文件夹中的每个软件包中调用的命令,并且
--stream标志将使我们能够在终端中查看结果的输出。
结果,根目录中的
package.json将如下所示:
现在,要运行测试,我们只需要从项目的根目录运行命令:
yarn test

Lerna的版本升级
lerna可以应付的下一个流行任务是更新软件包版本。 想象一下,在实施测试之后,我们决定将库从1.0.0升级到2.0.0。 为此,只需在根
package.json的
脚本字段中添加
“ update:version”:“ lerna version --no-push”行,然后从根目录中运行
yarn更新:version 。 添加了
--no-push标志,以便在更新版本后,更改不会发送到远程存储库,而
lerna默认情况下会执行此操作(不带此标志)。
结果,我们的根
package.json将如下所示:
运行版本更新脚本:
yarn update:version
接下来,将要求我们选择要切换到的版本:

通过单击
Enter,我们将获得更新版本的软件包列表。

我们输入
y确认更新,并收到有关更新成功的消息。

如果我们尝试运行
git status命令,则该消息
什么也没有提交,工作树为clean ,因为
lerna version不仅会更新软件包版本,还会创建一个git commit和标记来指示新版本(本例中为v2.0.0)。
与lerna版本团队合作的功能如果在根
package.json的
脚本字段中添加
“ version”:“ lerna version --no-push”行,而不是
“ update:version”:“ lerna version --no-push”行 ,则很可能会遇到意外行为,并且红色控制台。 事实是,默认情况下,
npm-scripts在更新软件包版本后立即调用
version命令(保留脚本),从而导致递归调用
lerna version 。 为了避免这种情况,只需为脚本指定其他名称即可,例如
update:version ,就像我们在示例中所做的那样。
结论
这些示例显示了
lerna与
纱线工作区结合的所有可能性的百分之一。 不幸的是,到目前为止,我还没有找到有关使用俄语的单一存储库的详细说明,因此我们可以假设这已经开始了!
链接到测试项目存储库。