发布于 2026-01-06 2 阅读
0

创建设计系统单体仓库 我们要构建什么?什么是 Lerna?什么是单体仓库?为什么要使用 Lerna?创建你的第一个单体仓库 文件夹结构 常用命令 没那么可怕👻 参考资料 DEV 的全球展示挑战赛 由 Mux 呈现:展示你的项目!

创建设计系统单体仓库

我们正在建造什么?

Lerna是什么?

什么是单体仓库(monorepo)?

为什么要使用Lerna?

创建你的第一个单体仓库

文件夹结构

常用命令

其实没那么可怕👻

参考

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

在创建设计系统时,将功能拆分成更小更独立的模块(或包)通常很有用。但如果您决定单独交付每个组件,或者将实用程序模块与组件一起交付,您就会陷入困境

你会把它重构到一个独立的 Git 仓库和 NPM 包中吗?如何管理这些?比如共享构建/测试流程?如何创建一个可以轻松启动而无需过多维护的开发环境npm link这就是 Lerna 的用武之地。

本文将介绍Lernamonorepo 的概念,以及如何使用它们来创建管理新的设计系统。您也可以直接跳到此处查看源代码

我们正在建造什么?

以下是我们将要构建的内容以及我们将使用的技术的简要概述:

  • 单体仓库
  • Lerna提供技术支持(最受欢迎的选项)
  • 需要Yarn(用于管理跨包或“工作区”的链接依赖项)
  • React UI 组件库(但也可以是任何东西,更多信息请参见示例)

Lerna是什么?

Lerna 是一个用于管理包含多个包的 JavaScript 项目的工具。

我说的JavaScript项目,指的是一个单独的Git仓库。我说这个项目有多个包,指的是同一个Git仓库里有多个模块(比如NPM、Serverless Functions,甚至可能是Composer或其他语言的模块)。

什么是单体仓库(monorepo)?

这就是单体仓库(monorepo)。一个仓库可以存放多个项目/模块等等。

./what-is.png

许多大型公司,例如GoogleFacebook,以及像GatsbyVercel这样的小型公司,都使用单体仓库 (monorepo) 来帮助管理大型项目。以 Gatsby 为例,他们的单体仓库包含了 Gatsby CLI、入门模板,甚至还有插件——所有内容都位于同一个仓库中,确保你可以对任何特定的软件包进行本地修改。

为什么要使用Lerna?

当您想要创建一个单体仓库并更轻松地同时管理多个软件包时。

  • 您可以将多个包链接在一起(例如,一个core包可以被其他包使用——类似于 Yarn Workspaces 或其他类似方式npm link)。
  • 将软件包及其提交历史记录导入到单体仓库中
  • 一次性发布多个软件包并递增它们的软件包版本

通常情况下,无需使用 Lerna,只需利用相同的依赖项(例如 Yarn Workspaces)即可完成所有这些操作,但 Lerna 本身就提供了许多此类功能。这省去了编写常用脚本和工作流的时间。

创建你的第一个单体仓库

既然我们已经了解了 Lerna 和 monorepos 是什么,那就让我们实际启动一个吧!

  1. 为 monorepo 创建一个新文件夹:mkdir your-monorepo && cd $_
  2. 运行 Lerna 安装程序:npx lerna init

这将使用以下文件和结构引导您的项目:

   lerna-repo/
     packages/
     package.json
     lerna.json
Enter fullscreen mode Exit fullscreen mode
  1. 要启用 Yarn 工作区(用于管理共享依赖项和链接包),请将以下内容添加到package.json
   {
     "name": "my-design-system",
     "private": true,
     "workspaces": ["packages/*"]
   }
Enter fullscreen mode Exit fullscreen mode
  1. 请确保程序lerna.json能够从文件夹中拾取软件包/packages/,我们将把每个设计系统模块(或软件包)放置在该文件夹中:
   {
     "packages": ["packages/*"],
     // Doesn't version the monorepo - keeps version to packages
     "version": "independent",
     "npmClient": "yarn",
     "useWorkspaces": true
   }
Enter fullscreen mode Exit fullscreen mode

文件夹结构

完成lerna init上述流程和配置后,您应该使用类似于下面的文件夹结构:

./folder-structure.png

在这个文件夹内,/packages你可以放置任何你想要用来拆分项目的包(也就是 NPM 模块)。例如,你可以创建 ` <site>`websitecomponents`<components>` 文件夹,一个文件夹包含网站,另一个文件夹包含组件和设计系统。

所有包都应该位于同一文件夹层级。这意味着你不应该嵌套包(就像components/button嵌套文件夹一样)。/packages文件夹内的每个子文件夹都应该代表一个所需的 NPM 模块。

如果要嵌套模块,父文件夹应该只有一个模块,理想情况下,嵌套模块应该相互链接(从根目录下的模块链接/packages)。嵌套模块可以取消链接,但它们将无法在其他模块中使用(除非您链接父模块)。

请记住,您并非必须使用/packages文件夹或名称。如果您更改配置package.jsonlerna.json则可以将 NPM 模块放在任何文件夹(或子文件夹)中。

常用命令

现在你已经有了你的第一个 monorepo,让我们来学习一些你会经常用到的 Lerna 常用命令。

首先,你肯定需要使用 Lerna 来创建新的软件包并将它们链接起来。然后,你可以通过对所有软件包运行命令或发布到 NPM(如果你喜欢的话,甚至可以使用传统的提交方式)来深入挖掘。

创建新包

  1. 进入 packages 文件夹:cd packages
  2. 为软件包创建一个文件夹,并导航到该文件夹​​:mkdir your-package-name && cd $_
  3. 使用 npm 或 yarn 创建一个新项目:(yarn init版本号从 0.0.0 开始——Lerna 会在首次发布时自动递增版本号)

如果您拥有支持私有包的 NPM 组织帐户,则可以将以下内容添加到模块的单独配置中package.json

"publishConfig": {
    "access": "restricted"
}
Enter fullscreen mode Exit fullscreen mode

安装本地软件包作为依赖项

你经常会发现自己想要在设计系统的一个包中在另一个包中使用(例如core在你的包中使用一个包components,或者button在……中使用form)。

在这种情况下,Lerna 有一个命令lerna add可以处理将本地包链接到另一个包的过程(使用yarn link添加到package.json)。

  1. 进入Lerna项目根目录:cd my-monorepo
  2. 运行以下命令,将第一个软件包 添加第二个软件包中:
   lerna add button --scope=form
Enter fullscreen mode Exit fullscreen mode

在这种情况下,form它将button作为依赖项。

您可以通过运行以下命令将软件包安装到monorepo 中的所有软件包lerna add package-name中。

对所有软件包运行命令

Lerna 提供了一个命令,可用于在每个包中运行相同的命令。运行lerna run test此命令后,将运行一个脚本,该脚本会遍历每个包并运行其中声明的测试脚本package.json

lerna run test --stream
Enter fullscreen mode Exit fullscreen mode

建议您创建一个单独的包,其中包含所有测试依赖项,并将其添加到所有其他模块中,这样可以将依赖项隔离到一个位置,从而更容易管理所有包中的测试。

  1. 理想情况下,您可以将测试设置在某个utils软件包中testing
  2. 将包添加testing到所有组件(用于lerna add一次性添加到多个包
  3. 为每个组件添加test脚本package.json
  4. 使用以下方式运行测试lerna run test

移除所有软件包的依赖关系

如果你在某个软件包中添加了不再需要的依赖项,Lerna 提供了一个命令,可以从 Yarn 工作区(以及共享依赖项)中删除它们。

  1. 前往 Lerna 项目根目录
  2. 运行以下命令:lerna exec -- yarn remove dep-name

发布所有软件包

当您需要将软件包发布到 NPM 时,Lerna 可以帮您完成这个过程。登录后,您可以运行 Lerna 的发布命令,创建一个包含所有已更新软件包的新版本,同时也会更新 NPM 上的所有软件包。

  1. 登录 NPM:npm login
  2. 运行发布脚本:lerna publish

版本分离和发布

如果出于某种原因,您需要完全控制版本控制,Lerna 可以将版本控制和发布拆分为两个命令。如果您希望更好地控制版本和发布,这将非常有用。

您可以手动运行:

lerna version
Enter fullscreen mode Exit fullscreen mode

然后按照提示更新各个版本号。

然后你可以编写一个发布脚本,读取最新的标签(手动更新过的标签)并将其发布到 NPM:

lerna publish from-git --yes
Enter fullscreen mode Exit fullscreen mode

配置

自动常规提交

Lerna 支持使用 常规提交标准 在 CI 环境中实现语义版本控制的自动化。

这使得开发者能够提交如下消息:

git commit -m "fix: JIRA-1234 Fixed minor bug in foo"
Enter fullscreen mode Exit fullscreen mode

然后,在持续集成 (CI) 环境中,可以根据类似上述的提交更新软件包版本并将其发布到 NPM。这可以通过配置 CI 环境来运行以下命令:

lerna publish --conventional-commits --yes
Enter fullscreen mode Exit fullscreen mode

如果您不想在每次发布时都传递标志,请将以下内容添加到您的 lerna.json 文件中。

lerna.json

"command": {
    "publish": {
       "conventionalCommits": true,
       "yes": true
    }
}
Enter fullscreen mode Exit fullscreen mode

强制执行常规承诺

使用常规提交是一回事,但真正强制执行这些提交又是另一回事。

强制执行这些规则意味着使用提交检查流程来解析所有提交,并确保它们符合常规的提交标准。

由于记住提交的确切语法可能很麻烦,因此强烈建议您设置一个提交 CLI 流程(例如 commitzen),引导开发人员完成常规提交,并确保每次都符合规范。

这个过程比较复杂,所以我会在另一篇文章中详细介绍。

其实没那么可怕👻

希望这篇文章能帮助大家揭开单体仓库的神秘面纱,了解如何创建和使用它们。单体仓库是一种高效的工作流程,有助于简化和扩展开发。无论在设计系统领域内外,学习单体仓库都是一项非常实用的技能,因为大多数大型项目最终都会采用单体仓库结构。

我使用这种工作流程创建了一个包含多个 Storybook 的单体仓库,这样我就可以拥有一个类似“设计系统笔记本”的东西。这样,我就可以记录任何前端框架(例如 React 或 Vue)的笔记,并将所有笔记集中在一个地方。

还有什么我遗漏的,你还是不明白的吗?请在评论区或推特上告诉我,我会尽力解答👍

请务必查看我的 Instagram 帖子,里面有您可以保存以备后用的快速参考资料:

./Slide07_-_CLI_Cheatsheet.png

参考

示例

官方文件

教程

文章来源:https://dev.to/whoisryosuke/creating-a-design-system-monorepo-e2j