网站建设制作深圳,网上超市系统,微信公众平台是什么,wordpress怎么做响应式网站1.前言
通常#xff0c;我们会根据自身业务的实际情况#xff0c;将通用的组件、逻辑等提取成NPM包#xff0c;方便以后复用。但这些提取出来的NPM包可能互相之间存在依赖#xff0c;如果仍然采用 Multirepo 的形式进行管理#xff0c;则在包的版本管理、依赖管理、调试等…1.前言
通常我们会根据自身业务的实际情况将通用的组件、逻辑等提取成NPM包方便以后复用。但这些提取出来的NPM包可能互相之间存在依赖如果仍然采用 Multirepo 的形式进行管理则在包的版本管理、依赖管理、调试等诸多方面存在不便。 Monorepo 能很好的解决上述问题为更加方便的使用 Monorepo 来管理我们的项目我们需要一些趁手的工具Lerna Yarn Workspace 的组合就是这样一件优秀的工具。然而 Lerna 中途经历过较大的改动其文档也不是那么容易看明白中文材料大多使用较老版本的 Lerna使用上和较新版本存在差异。 本文将介绍较新版本的 Lerna 如何结合 Yarn Workspace 管理 Monorepo 项目后续操作在 Lerna V7 和 V8 中经过实践。
2.Lerna Yarn Workspace
其实除了 Lerna Yarn Workspace 的方案外还有其他方案也可以帮助我们管理 Monorepo 项目比如 pnpm 等但我选择 Lerna Yarn Workspace 一方面是由于习惯了使用 yarn只要引入 Lerna 即可另一方面公司的基建对 yarn 也有很好的支持所以选择了 Lerna Yarn Workspace。 在使用 Lerna Yarn Workspace 时两者的分工有所不同
Yarn 负责依赖管理在 install 时将子包相同的依赖安装到根目录下的 node_modules 中避免了在子包中重复安装。同时 Yarn 也可以处理子包之间的相互依赖关系使用软链的方式连接各个子包。Lerna 则负责子包的发布包括版本号更新、依赖更新、发布等。
3.入门实践
3.1.初始化
3.1.1.项目初始化
首先你需要初始化 Monorepo 项目新建一个目录 my-monorepo-project进入到目录中执行
yarn init这一步完成后项目根目录下会出现 package.json这里需要将 private 字段设为 true。
3.1.2.Workspaces 初始化
接下来进行 Workspaces 初始化在根目录新建 packages 文件夹并在 packages.json 中新增 workspaces 配置
workspaces: [packages/*
]workspaces 字段定义了一个包含多个路径的数组这些路径指向了项目中的各个子包的位置。如上配置就是将 packages 目录下的所有项目都看做是子包。 这一步完成之后就可以在根目录下执行 yarn 安装依赖了假设我们的项目目录如下
/my-monorepo-project
|-- packages
| |-- package1
| |-- package2
| |-- package3
|-- package.json
|-- yarn.lock其中 package1 依赖了 package2则 yarn 之后my-monorepo-project 的根目录下会出现 node_modules 文件夹在 node_modules 查看各个子包对应的目录会发现它们是以软链的形式链接到各自的源码目录中。
值得注意的是此时就算 package1 的 package.json 中没有声明对 package2 的依赖但也可以直接在 package1 中引用 package2 了。但当我们发布后由于 package1 没有声明对 package2 的依赖用户在安装 package1 时不会同时安装 package2就会造成运行异常。正确的做法仍然需要在 package1 的 package.json 中声明对 package2 的依赖不过不要通过 yarn workspace package1 add package2的方式添加依赖这样 package2 会从 npm 上下载而不是链接到本地源码。
3.1.3.Lerna初始化
现在就可以引入 Lerna 了在根目录中继续执行
yarn add lerna -D
npx lerna init 如此一来在根目录下就会新增 lerna.json 文件其内容是
{$schema: node_modules/lerna/schemas/lerna-schema.json,version: independent,npmClient: yarn
}在较早版本的 Lerna 生成的 lerna.json 文件中还需要设置 useWorkspaces 字段不过Lerna 7 和 8 中已经不用设置该字段了。 另外需要注意 version 字段的值。version 可以设置为具体的版本号比如 0.0.1此时 Lerna 将采用固定模式Fixed/Locked mode管理子包版本即有的子包将共享同一个版本号。Lerna 默认采用该方式version 初始值为 0.0.0。 也可以将 version 设置为 independent表示每个子包都可以独立地管理自己的版本号Independent mode当发布时 Lerna 会让你为子包选择版本号。由于我是将已有的项目改造为 Monorepo 项目各子包已经独立发版很长时间了所以将 version 改成了 independent。
3.2.开发
完成初始化后我们就可以开发我们的子包了。在开发过程中我们可能需要添加第三方依赖也有可能需要运行子包的 scripts 脚本。我们来看看如何执行这些常见的操作。
3.2.1.添加依赖
如果需要添加第三方依赖可以将依赖添加到 workspaces 根目录:
# 在任何目录执行
yarn add 依赖名 -W# 或者在根目录中执行
yarn add 依赖名这样依赖会被安装到根目录的 node_modules 中所有子包都可以引用。
如果需要为某个子包单独添加某个依赖可以执行:
# 在任何目录执行
yarn workspace 子包名 add 依赖名# 或者在进入子包对应的目录中执行
yarn add 依赖名这样依赖只会被会被安装到子包对应目录下的 node_modules 中其他子包不能直接引用。注意子包名指的是子包 package.json 中 name 字段的值不是子包的目录名。
我们可以通过如下命令查看子包间的依赖关系防止日后理不清子包的依赖关系
yarn workspaces info3.2.2.运行script
如果需要执行某个子包中的脚本可以执行:
yarn workspace 子包名 run build这样就会运行子包的 build 命令。
3.3.发布
整个开发过程都是由 Yarn 进行管理但 Yarn Workspace 不具备发布的能力这时就需要借助 Lerna 的能力了。
3.3.1.检查更新
需要检查自上次发布以来在 Git 中已经提交但尚未发布的修改执行:
npx lerna changed该命令的结果形如
# 没有未发布的修改
lerna notice cli v7.4.2
lerna info versioning independent
lerna notice Current HEAD is already released, skipping change detection.
lerna info No changed packages found# 有未发布的修改
lerna notice cli v7.4.2
lerna info versioning independent
lerna info Looking for changed packages since package10.0.1
package1
package2该命令的结果不仅包含发生修改的子包本身还包括依赖了该子包的其他子包。比如 package2 发生修改则依赖它的 package1 也会被识别为需要发布因为需要修改 package1 依赖的 package2 的版本。
3.3.2.更新版本号
之前说过在 lerna.json 中配置 version 为 independent 表示每个子包可以独立地更新版本号。假设我们修改了 package1 的代码首先需要提交修改否则发布时会因为没有提交记录而被 Lerna 卡住。 接下来需要更新版本号这一步不需要直接修改 package.json而是由 Lerna 帮我们修改执行
npx lerna version --no-private–no-private 表示不更新私有包因为他们不会被发布。命令执行之后Lerna 会自动识别需要更新版本的子包即 lerna changed 的结果并向用户确认下一个版本号是多少。用户依次确认所有需要更新的子包的新版本号后Lerna 会打 Tag并push。 这一步不仅会修改 package.json 中的 version也会修改依赖的版本。比如 package2 更新了则在 package1 的 package.json 中不仅自身的版本号会更新其依赖的 package1 的版本也会跟着改变。
3.3.3.发布
发布就很简单了执行
npx lerna publish from-package即可将更新的子包发布到NPM。
4.踩坑
我是将已经独立发版一段时间的好几个子包改造为使用 Monorepo 架构进行管理。由于 Lerna 基于 Tag 判断有哪些子包需要发布由于之前发布子包时没有打Tag所以执行 npx lerna changed会提示 lerna success found 9 packages ready to publish意思是所有的子包都要发布。但执行 npx lerna publish from-package时由于本地包和 npm 上的版本相同会提示 No unpublished release found意思是没有需要发布的包。 为了解决上述问题需要补一下Tag具体方法是执行 npx lerna version --no-privateLerna 会让填写每个子包的新版本号没有修改的子包版本号可以保持不变。执行完毕后再执行 npx lerna changed会提示 Current HEAD is already released, skipping change detection... No changed packages found即达成目的。 随后执行 npx lerna publish from-package发布需要更新的子包即可。如果没有要发布的子包这一步也可以不执行。
5.参考
Yarn文档Yarn WorkspacesLerna文档Lerna文档翻译Lerna 备忘清单Lerna Yarn workspace 使用总结