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

使用 Lerna 管理你的 JavaScript monorepo

使用 Lerna 管理你的 JavaScript monorepo

让我们深入了解一下勒纳!

Lerna是一个便捷的命令行工具,可用于管理包含多个包的 JavaScript 项目。它对开源项目和私有项目都非常实用。

这篇文章旨在提供一些入门知识,而非深入探讨。如果您有任何改进建议或疑问,请在下方留言!

什么是包裹?

项目通常包含许多组件;例如前端、服务器、微服务等等。这些组件可以单独开发、版本控制和发布,同时都托管在同一个代码仓库中,这使得开发访问和项目跟踪更加便捷。您可以将这些独立组件视为软件包。

Lerna 能提供哪些帮助?

Lerna 使用 Git 和 NPM,通过命令行界面 (CLI) 为您的众多项目包创建最佳工作流程lerna。这包括版本控制、分发、测试等等。

这个工具让我很兴奋,因为它省去了手动遍历项目中的每个包来执行繁琐操作的麻烦。表面上看,它只是一个简单的工具,但它可以进行一些非常巧妙的配置,如果使用得当,可以大大节省使用单体仓库的时间。

有趣的事实:

您在项目网站代码库顶部看到的七头怪兽描绘的是希腊神话中的九头蛇,也称为勒那九头蛇。摘自维基百科条目

九头蛇拥有许多头,具体数量因版本而异。后来的九头蛇传说中又赋予了它再生能力:每砍掉一个头,九头蛇就会长出两个新头。

我觉得这个吉祥物非常适合这款工具。🐉

准备工作

正如我上面提到的,这个工具可以通过几种方式进行配置以满足您的需求,但在这篇文章中,我们只是要尽快上手运行,避免遇到太多麻烦。

在继续操作之前,请先全局安装命令行实用程序:

# via npm
npm install -g lerna
# via yarn
yarn global add lerna
Enter fullscreen mode Exit fullscreen mode

现在你需要决定如何以及在哪里进行设置。Lerna 可以初始化在一个空目录中,也可以添加到现有项目中。无论哪种方式,lerna init在你的项目文件夹中运行命令后,你都会得到以下新增内容:

lerna.json
package.json
/packages
Enter fullscreen mode Exit fullscreen mode

如果你直接在裸目录上运行它,它就能运行git init。请确保添加远程仓库,以便你可以推送版本更新。

如果您已经安装了某个package.json依赖项,它不会覆盖它,但会将其添加lerna为开发依赖项。请务必npm install之后进行检查。

新添加的packages/目录将用于存放所有软件包。“packages”只是默认目录。说到软件包……

您新lerna.json设置的配置将在执行命令时使用。您可以在这里查看完整的选项列表,但我们先来看几个例子:

  • packages这告诉 Lerna 在哪里可以找到它可以操作的软件包。默认情况下,这是 `<package_name>` ["packages/*"],它会遍历 `<package_name>` 下的所有目录packages/,因此它是自动生成的。
  • version此值告诉 Lerna 当前项目版本。默认情况下,此值处于“固定”模式,使用语义化版本控制(semver)值,并在运行版本命令时自动递增。但如果您希望独立管理各个包版本,则可以选择更改此值。您可以通过运行以下命令independent自动设置此值lerna init--independent
  • npmClient用于运行命令的客户端。默认值为npm,但您可以yarn根据需要将其更改为。
  • command.publish.ignoreChanges这可以是一个 glob 类型数组,Lerna 在查找更改以生成新版本时会忽略这些类型。例如,README 文件、CHANGELOG 文件、任何测试或基准测试等。

差不多就是这样了!你可以在这里添加新的包packages/。如果你在现有的根级项目中初始化了 Lerna,可能需要进行一些重新配置。只需确保每个包都有一个有效的package.json.htaccess 文件,Lerna 可以通过它的命令调用该文件即可。例如:

/packages
  /cli
    index.js
    package.json
Enter fullscreen mode Exit fullscreen mode

请注意,Lerna 不需要作为每个软件包的依赖项存在。

小贴士:

您可能更喜欢手动设置软件包,但如果您要设置新的软件包,一个很棒的命令是 ` lerna create [name].`。它会为您处理所有事情,创建适当的结构并帮助您创建 `.` package.json(与 `.` 相同npm init)。

常用命令

我竭尽全力lerna init帮助lerna create你入门,现在让我们来看看你在常规开发工作流程中可能会用到的一些命令。

请注意,命令支持筛选选项,例如--scope仅对某些软件包执行、--no-private排除私有软件包以及--since [ref]仅对自指定 Git 引用以来发生更改的软件包运行。

lerna run

此命令将在每个包中运行附加到其上的脚本名称以及配置的脚本npmClient

让我们来看一个来自Firefox Accounts monorepo的例子:

// package.json
"scripts": {
  "format": "lerna run test",
}

// packages/fxa-content-server/package.json
"scripts": {
  "test": "node tests/intern.js --unit=true",
}

// packages/fxa-payments-server/package.json
"scripts": {
  "test": "npm-run-all test:*",
}

// packages/fxa-payments-server/package.json
"scripts": {
  "test": "scripts/test-local.sh",
}
Enter fullscreen mode Exit fullscreen mode

这些只是该仓库中列出的一小部分软件包,但你应该明白我的意思了。现在,当你npm run test在根目录运行 Lerna 时,它会遍历每个软件包,并有效地npm run test在每个目录中运行。

有几种方法可以自定义其运行方式:

# Pass args to the scripts
lerna run <script> -- [..args]
# Run scripts simultaneously, good for long-running processes 
lerna run <script> --parallel
# Ignore non-zero exit codes when running
lerna run --no-bail <script>
Enter fullscreen mode Exit fullscreen mode

lerna exec

使用此命令可在每个包内运行任意命令。这可能与之前的命令类似run,如果您愿意,也可以将其设置为执行相同的操作,但此命令可以运行任何内容,而不仅仅是 NPM 脚本。

来看看 Antony Budianto 的Create React App Universal CLI是如何使用它的:

// package.json
"scripts": {
  "clean:build": "lerna exec -- rimraf lib",
  "demo:start:client": "lerna exec --scope cra-universal-demo -- npm start",
}
Enter fullscreen mode Exit fullscreen mode

您可以看到,对于所有正在运行的包,npm run clean:build该命令会rimraf lib在每个包目录中执行;而对于后续命令,例如demo:start:client执行,npm start则使用--scope 筛选选项仅在名为 的包中运行cra-universal-demo

lerna version

此命令会对自上次发布以来发生更改的软件包执行版本升级。它不会对任何未发生更改的软件包运行,如果您已进行配置,ignoreChanges它也会忽略这些文件。

默认情况下,运行该lerna version命令会提示您如何执行每次版本升级。您还可以提供语义版本关键字(例如 `--version` prerelease)或显式值(例如 `--version` 1.4.8)。

完成上述操作后,Lerna 将运行生命周期脚本,提交并标记更改,然后将所有内容推送到您的 Git 远程仓库。

您可以通过多种方式配置此命令。例如:

# Create a release on GitHub or GitLab
lerna version --create-release github
# Perform the changes on the current commit and don't push
lerna version --amend
# Use Convention Commits Specification to determine the version bump and generate CHANGELOG.md files
# https://www.conventionalcommits.org/en/v1.0.0/
lerna version --conventional-commits
# Provide your own version bump message, where %v is replaced with the new version
lerna version -m "chore(release): publish %v"
Enter fullscreen mode Exit fullscreen mode

lerna publish

你或许能猜到这条命令的作用。顾名思义,这条命令会将每个软件包的新版本发布到 NPM 注册表。默认情况下,它会在version后台调用相应的命令,发布自上次发布以来的更新,但还有其他几个选项:

# Publish packages that have changed since the last release
lerna publish
# Explicitly publish packages tagged in the current commit
lerna publish from-git
# Handy for when you’d like to manually increment package versions but want to be able to automate publishing
# Explicitly publish packages where the latest version is not present in the registry
# Handy for when you need to retry a publish (e.g. it previously failed to publish)
lerna publish from-package
Enter fullscreen mode Exit fullscreen mode

它还提供多种选项以满足您的需求。例如:

# Publish to NPM with a given dist-tag (instead of `latest`)
# https://docs.npmjs.com/cli/dist-tag 
lerna publish --dist-tag next
# If you have two-factor authentication set up to publish
lerna publish --otp 818391
# Automatically accept prompts that come up during the publish process
lerna publish --yes
Enter fullscreen mode Exit fullscreen mode

总结

我希望这篇文章能让你充分感受到 Lerna 的强大之处。我非常期待在所有包含多个组件的项目中使用它。

如果您需要一些其他人如何使用 Lerna 的示例,Lerna 网站提供了一个很好的仓库列表,其中包括JestChrome WorkboxWordPress GutenbergVue CLIESLint Typescript等。

如果您觉得这篇文章有趣,并且渴望了解更多(抱歉用了个双关)开发者社区的内容,请查看以下其他用户的精彩文章:

另外,如果你有13分钟时间,强烈建议你看看Ben Awad的这段精彩视频,他在视频里演示了如何使用Lerna。这段视频帮助我更好地理解了它的工作原理,而且我确信我在这篇文章中也用到了一些视频里的信息。

我很想看看你是如何使用Lerna的!如果你有任何意见或问题,请在评论区留言😎。

文章来源:https://dev.to/jody/using-lerna-to-manage-your-javascript-monorepo-4eoo