文章目录
Lerna基本概念
Lerna 是一个用来优化托管在 git\npm 上的多 package 代码库的工作流的一个管理工具,可以让你在主项目下管理多个子项目,从而解决了多个包互相依赖,且发布时需要手动维护多个包的问题。
主要功能:
- 为单个包或多个包运行命令 (lerna run)
- 管理依赖项 (lerna bootstrap)
- 发布依赖包,处理版本管理,并生成变更日志 (lerna publish)
关于monorepo
幽灵依赖
未在项目 package.json 中声明的依赖,但在项目中依然可以意外的被正确引用。
引起原因
- 全局模块:在某些开发环境中,如果使用了全局安装的模块,那么项目可能会隐式地依赖这些全局模块,而没有在项目的依赖文件中声明。
- 手动引入:开发者可能手动在代码中引入了某个模块,但没有在依赖管理文件中添加相应的依赖声明。
- 软链接:在monorepo中,有时会通过软链接(symlink)来共享代码,这可能导致一个项目依赖于另一个项目的模块,而这种依赖没有在依赖管理文件中体现。
- 依赖传递:当一个项目依赖于另一个包,而这个包又依赖于其他包时,可能会出现间接依赖(传递依赖)。如果传递依赖没有被正确管理,就可能出现幽灵依赖。
如何解决
- 明确声明依赖:确保所有直接和间接依赖都在项目的依赖管理文件中明确声明。
- 使用工作区:在monorepo中,使用如yarn workspaces或npm workspaces来管理工作区内的依赖关系,确保所有共享的依赖都被正确处理。
pnpm如何解决幽灵依赖?
- npm和yarn 处理依赖的思想理念:把相同的依赖包进行提升的方式,提升到项目顶层,可以实现依赖共享,同时允许子依赖被父级依赖访问,即使它们没有被明确地声明。
- pnpm 使用符号链接(symlinks)来创建一个更加严格的依赖树,这意味着只有那些被明确声明为项目依赖的包才能在代码中被访问。
- pnpm所有的包都被存储在一个 .pnpm 目录下,并且每个包都有自己的 node_modules 目录,其中包含指向全局存储位置的硬链接。这种结构确保了每个包的依赖都是隔离的,不会被其他包意外访问。
node_modules
└── .pnpm
│── <package1>
│ └── node_modules
│ └── <package1> -> <全局存储位置>/<package1>
└── <package2>
└── node_modules
└── <package2> -> <全局存储位置>/<package2>
解决痛点
- 代码共享,调试便捷: 一个依赖包更新,其他依赖此包的包/项目无需安装最新版本,因为 Lerna 自动 Link
- 安装依赖,减少冗余:多个包都使用相同版本的依赖包时,Lerna 优先将依赖包安装在根目录
- 规范版本管理: Lerna 通过 Git 检测代码变动,自动发版、更新版本号;两种模式管理多个依赖包的版本号
- 自动生成发版日志:使用插件,根据 Git Commit 记录,自动生成 ChangeLog
如何使用
- 下载lerna工具
npm install lerna -g
- 新建项目文件
mkdir lerna-demo
在当前目录下创建文件夹lerna-demo,然后使用命令lerna init
执行成功后,目录下将会生成这样的目录结构。,一个 hello world级别的 lerna 项目就完成了。
- packages(目录)
- lerna.json(配置文件)
- package.json(工程描述文件)
- 模式选择
- 固定模式:所有包的主版本号和次版本都会使用lerna.json配置里的version字段定义的版本号,如果某一次只修改了其中一个或几个包,但修改了配置文件里的主版本号或次版本号,那么发布时所有的包都会统一升级到该版本并进行发布,单个的包如果想要发布只能修改修订版本号进行发布。
- 独立模式:每个包使用独立的版本号。
- 安装依赖
yarn add vue@next typescript -W
搭建业务组件库(yarn workspace + Lerna)
能力分工:Lerna 将依赖管理交给 yarn workspace;Lerna 承担依赖发布能力。
和pnpm Workspaces对比
lerna:
优点:
- 版本管理:Lerna 允许对 monorepo 中的多个包进行统一的版本管理,方便进行版本同步或独立版本更新。
- 自动发布:它能够自动化处理复杂的发布流程,包括版本号更新、生成 changelog、以及将更新发布到 npm。
- 运行脚本:它可以在多个包中同时运行相同的脚本命令,这对于构建和测试整个项目很有帮助。
- 过滤执行:Lerna 提供了强大的过滤选项,允许你只对改变的包或特定的包运行命令。
- 团队内部对lerna的熟练程度
缺点:
- 性能:Lerna 并没有专门针对依赖安装进行优化,大型项目可能会遇到性能瓶颈。
- 重复依赖:多个包如果使用相同的依赖,Lerna 不会自动优化它们的存储,可能会导致重复的依赖安装。
- 可能会导致幽灵依赖,需要明确版本依赖
pnpm:
缺点:
- 不是专门的版本管理工具:虽然 pnpm Workspaces 提供了对多包的依赖管理,但缺少了像 Lerna 那样对包版本进行管理和发布的功能。
优点:
- 高效的存储:pnpm 通过使用硬链接和符号链接来存储依赖,有效地减少了磁盘空间的占用。
- 快速的安装:在依赖安装上,pnpm 通常比 npm 和 Yarn 更快,特别是在 monorepo 场景下。
- 严格的依赖隔离:pnpm 的 node_modules 结构更加严格,避免了潜在的依赖冲突问题。
- 直观的 workspace 管理:pnpm Workspaces 提供了直观的命令来执行 workspace 内的操作和依赖管理。
搭建组件库
使用lerna从零搭建一个 平台基础组件库项目:
- 项目初始化
lerna init
// lerna.json
{
"packages": [
"packages/*" // 表示管理packages下的所有模块
],
"npmClient": "yarn", // 依赖包的安装交给yarn
"useWorkspaces": true, // 是否使用空间,lerna本身不使用workspace,yarn要使用。
"version": "0.0.0"
}
//package.json
{
"name": "root",
"private": true, // root库作为packages管理角色不需要发布到npm
"devDependencies": {
"lerna": "^4.0.0"
},
"workspaces": [ //开启Yarn workspaces
"packages/*"
]
}
- 子项目创建
lerna create newProject
- 通过yarn安装子项目需要的所有依赖
yarn install
或yarn workspace <package-name> [add|remove] <library> [-D|-S]
- 使用yarn+workspaces依赖管理
在sub-package-1、sub-package-1中安装pretty-format,该依赖会被放在对应package的node_modules中。
再执行yarn install,2个包中相同的pretty-format会被提升到root的node_modules中。 - 版本发布
lerna publish
- 配置打包工具rollup,支持按需导入
- Storybook开发阶段的调试
- 安装必要插件
- eslint:约束代码风格,以及检测一些潜在错误
- husky:在git提交前采取强制eslint检查
- commitlint:commit说明检查,标准格式是三部分:Header(必须)、Body、Footer
- commitizen:给commit检查交互式输入,方便使用
pnpm 和 lerna 是两种不同的工具,它们在软件开发中扮演着不同的角色。下面是它们的主要区别:
pnpm
pnpm 是一个现代的包管理器,它旨在提供比传统包管理器(如 npm 和 Yarn)更快的安装速度和更少的磁盘空间使用。pnpm 通过使用硬链接和符号链接来共享全局存储中的依赖项,而不是在每个项目中复制它们。这使得 pnpm 在处理依赖项时非常高效。
主要特点:
高效的依赖项管理:pnpm 使用一个全局存储来存储所有依赖项,并通过链接来引用它们,这样可以节省磁盘空间并加快安装速度。
严格的依赖项解析:pnpm 遵循更严格的依赖项解析规则,确保每个包都使用其声明的确切版本。
支持 monorepo:pnpm 可以很好地与 monorepo 结构配合使用,它允许在同一仓库中管理多个项目,并且可以共享依赖项。
Lerna
Lerna 是一个用于管理包含多个包(packages)的 JavaScript 项目的工具。它主要用于 monorepo 设置,其中多个相关的包被存储在同一个版本控制仓库中。Lerna 可以帮助自动化许多与维护多包仓库相关的任务,如版本管理和依赖项安装。
主要特点:
版本管理:Lerna 可以自动更新多个包的版本,并生成相应的 changelog。
依赖项优化:Lerna 可以优化依赖项的安装,确保每个包只安装一次,即使在不同的包中声明了相同的依赖项。
脚本执行:Lerna 允许在 monorepo 中的所有包或特定包上执行命令,这有助于维护和测试。
区别总结
目的:pnpm 主要是一个包管理器,专注于提供高效的依赖项安装和管理;而 Lerna 是一个项目管理工具,专注于 monorepo 中的多包管理和自动化。
功能:pnpm 提供了依赖项共享和快速安装的功能;Lerna 提供了版本管理、依赖项优化和跨包脚本执行的功能。
使用场景:pnpm 可以与任何 JavaScript 项目一起使用,以提高依赖项管理的效率;Lerna 特别适用于那些需要在单个仓库中管理多个相关包的项目。
在实践中,pnpm 和 Lerna 可以一起使用。例如,一个使用 Lerna 管理的 monorepo 项目可以使用 pnpm 作为其包管理器,以获得更高效的依赖项安装和管理。这种组合可以为大型项目提供强大的工具支持,帮助开发者更有效地管理复杂的代码库。