使用Lerna搭建业务组件库

本文介绍了Lerna和pnpm在处理多package代码库中的幽灵依赖问题,比较了两者在版本管理、依赖隔离和性能方面的优缺点,并详细阐述了如何使用Lerna和pnpm搭建和管理业务组件库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

如何使用

  1. 下载lerna工具
    npm install lerna -g
  2. 新建项目文件
    mkdir lerna-demo 在当前目录下创建文件夹lerna-demo,然后使用命令 lerna init 执行成功后,目录下将会生成这样的目录结构。,一个 hello world级别的 lerna 项目就完成了。
  • packages(目录)
  • lerna.json(配置文件)
  • package.json(工程描述文件)
  1. 模式选择
    • 固定模式:所有包的主版本号和次版本都会使用lerna.json配置里的version字段定义的版本号,如果某一次只修改了其中一个或几个包,但修改了配置文件里的主版本号或次版本号,那么发布时所有的包都会统一升级到该版本并进行发布,单个的包如果想要发布只能修改修订版本号进行发布。
    • 独立模式:每个包使用独立的版本号。
  2. 安装依赖
    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从零搭建一个 平台基础组件库项目:

  1. 项目初始化
    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/*"
  ]
}

  1. 子项目创建
    lerna create newProject
  2. 通过yarn安装子项目需要的所有依赖
    yarn installyarn workspace <package-name> [add|remove] <library> [-D|-S]
  3. 使用yarn+workspaces依赖管理
    在sub-package-1、sub-package-1中安装pretty-format,该依赖会被放在对应package的node_modules中。
    再执行yarn install,2个包中相同的pretty-format会被提升到root的node_modules中。
  4. 版本发布
    lerna publish
  5. 配置打包工具rollup,支持按需导入
  6. Storybook开发阶段的调试
  7. 安装必要插件
    • 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 作为其包管理器,以获得更高效的依赖项安装和管理。这种组合可以为大型项目提供强大的工具支持,帮助开发者更有效地管理复杂的代码库。

### 使用 Lerna 创建 Vue 和 React 项目的指南 #### 初始化 Lerna 工作区 为了管理多个包,可以使用 `lerna` 来初始化工作区。这会创建必要的配置文件以及用于存放各个独立模块的目录结构[^2]。 ```bash npx lerna init ``` 此命令执行之后,在当前路径下将会生成 `.gitignore`, `lerna.json`, `package.json` 文件和一个名为 `packages/` 的文件夹。 #### 添加 Vue 应用程序作为子包 对于希望集成到单体仓库中的 Vue.js 前端应用来说,可以通过如下方式来新增: ```bash npx create-vue ./packages/vue-app --preset default cd packages/vue-app && npm install ``` 这段脚本利用官方提供的工具链快速搭建了一个基于默认设置的新建 Vue 项目,并安装依赖项。 #### 添加 React 应用程序作为另一个子包 同样的道理适用于添加 React 子包: ```bash npx create-react-app ./packages/react-app --template typescript cd packages/react-app && npm install ``` 这里选择了带有 TypeScript 支持模板版本的 Create React App 构建新应用程序并完成初始环境准备。 #### 配置共享逻辑和服务 考虑到两个前端框架之间可能存在共通的需求(比如 API 请求处理),可以在根级别定义额外的服务层或实用函数库供两者调用而无需重复造轮子。通过这种方式实现跨平台组件复用成为可能[^1]。 例如建立一个新的 JavaScript 或者 TypeScript 包用来封装 HTTP 客户端实例或者其他业务无关紧要但是又经常要用的功能片段。 #### 开发与构建流程优化建议 为了让开发体验更加流畅高效,推荐引入诸如 Webpack、Babel 这样的编译器插件以便更好地支持多语言特性;同时考虑加入 Storybook 来辅助 UI 组件的设计迭代过程。 另外值得注意的是,借助于 Lerna 提供的能力,能够轻松地同步不同包之间的版本号更新操作,简化发布流程的同时也减少了维护成本开销[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值