发布库
使用合适的工具,从 monorepo 将包发布到 npm 仓库可以非常流畅。
¥Publishing a package to the npm registry from a monorepo can be a smooth experience, with the right tools.
虽然本指南无法解决构建健壮软件包所需的所有编译、打包和发布配置问题,但它将解释一些基础知识。
¥While this guide cannot solve for every possible compiling, bundling, and publishing configuration needed for robust packages, it will explain some of the basics.
如果你想将部分 monorepo 软件包发布到 npm,则应遵循此设置。如果你不需要发布到 npm,则应该使用 内部包。它们的设置和使用更加简单。
¥You should follow this setup if you want to publish some of your monorepo's packages to npm. If you don't need to publish to npm, you should use an Internal Package instead. They're much easier to set up and use.
打包
¥Bundling
与 内部软件包 不同,外部包可以部署到 npm 并在本地使用。在本指南中,我们将把一个包打包到 ECMAScript 模块 (esm
) 和 CommonJS 模块 (cjs
),这是 npm 上最常用的格式。
¥Unlike Internal Packages, external packages can be deployed to npm and used locally. In this guide, we'll bundle a package to both ECMAScript modules (esm
) and CommonJS modules (cjs
), the most commonly used formats on npm.
设置构建脚本
¥Setting up a build script
让我们从使用 内部软件包 教程创建的包开始。
¥Let's start with a package created using the Internal Packages tutorial.
在那里,我们创建了一个 @repo/math
包,其中包含一些用于加减数字的辅助函数。我们认为这个包对于 npm 来说已经足够好了,所以我们要把它打包起来。
¥There, we created a @repo/math
package which contained a few helper functions for adding and subtracting numbers. We've decided that this package is good enough for npm, so we're going to bundle it.
我们将使用打包器将 build
脚本添加到 @repo/math
。如果你不确定选择哪一个,我们推荐 tsup
。
¥We're going to add a build
script to @repo/math
, using a bundler. If you're unsure which one to choose, we recommend tsup
.
使用包管理器将 tsup
安装到 ./packages/math
包中,然后为其创建构建脚本:
¥Install tsup
inside the ./packages/math
package using your package manager and then create a build script for it:
tsup
默认将文件输出到 dist
目录,因此你应该:
¥tsup
outputs files to the dist
directory by default, so you should:
-
将
dist
添加到你的.gitignore
文件中,以确保它们未提交到源代码管理中。¥Add
dist
to your.gitignore
files to make sure they aren't committed to source control. -
将
dist
添加到turbo.json
中build
的输出部分。¥Add
dist
to the outputs ofbuild
in yourturbo.json
.


这样,当 tsup
运行时,Turborepo 的输出就可以是 cached。
¥That way, when tsup
is run the outputs can be cached by Turborepo.
最后,我们应该更新包的入口点。在 package.json
文件中,将 main
更改为指向使用 CommonJS 模块的客户端的 ./dist/index.js
(cjs
),将 module
更改为指向使用 ECMAScript 模块的客户端的 ./dist/index.mjs
(esm
),并将 types
更改为指向类型定义文件。 - ./dist/index.d.ts
:
¥Finally, we should update our package entrypoints. Inside package.json
, change main
to point at ./dist/index.js
for clients using CommonJS modules (cjs
), module
to point at ./dist/index.mjs
for clients using ECMAScript modules (esm
), and types
to the type definition file - ./dist/index.d.ts
:
无需同时打包到 cjs
和 esm
。但是,我们建议这样做,因为它可以让你的包在更广泛的环境中使用。
¥It is not required to bundle to both cjs
and esm
. However, it is recommended, as it allows your package to be used in a wider variety of environments.
如果你在使用 main
、module
和 types
时遇到错误,请查看 tsup 文档。
¥If you run into errors by using main
, module
and types
, take a look at the tsup docs.
打包是一个复杂的话题,我们这里篇幅有限,无法一一详述!
¥Bundling is a complicated topic, and we don't have space here to cover everything!
在构建之前构建软件包应用
¥Building our package before our app
在运行 turbo run build
之前,我们需要考虑一件事。我们刚刚在 monorepo 中添加了一个 任务依赖 任务。packages/math
的 build
需要在 apps/web
的 build
之前运行。
¥Before we can run turbo run build
, there's one thing we need to consider. We've just added a task dependency into our monorepo. The build
of packages/math
needs to run before the build
of apps/web
.
幸运的是,我们可以使用 dependsOn
轻松配置这一点。
¥Fortunately, we can use dependsOn
to easily configure this.


现在,我们可以运行 turbo run build
,它会在构建我们的应用之前自动构建我们的包。
¥Now, we can run turbo run build
, and it'll automatically build our packages before it builds our app.
设置开发脚本
¥Setting up a dev script
我们的设置存在一个小问题。我们的软件包构建得很好,但在开发环境中运行不佳。我们对 @repo/math
包所做的更改未反映在我们的应用中。
¥There's a small issue with our setup. We are building our package just fine, but it's not working great in dev. Changes that we make to our @repo/math
package aren't being reflected in our app.
这是因为我们没有 dev
脚本来在工作时重建包。我们可以轻松添加一个:
¥That's because we don't have a dev
script to rebuild our packages while we're working. We can add one easily:
这会将 --watch
标志传递给 tsup
,这意味着它将监视文件更改。
¥This passes the --watch
flag to tsup
, meaning it will watch for file changes.
如果我们已经在 turbo.json
中设置了 开发脚本,则运行 turbo run dev
将同时运行 packages/math
开发任务和 apps/web
开发任务。
¥If we've already set up dev scripts in our turbo.json
, running turbo run dev
will run our packages/math
dev task in parallel with our apps/web
dev task.
我们的包现在可以考虑部署到 npm 了。在我们的 版本控制和发布 部分,我们将执行此操作。
¥Our package is now in a spot where we can consider deploying to npm. In our versioning and publishing section, we'll do just that.
版本控制和发布
¥Versioning and publishing
在 monorepo 中手动版本控制和发布包可能很繁琐。幸运的是,有一个工具可以让事情变得简单。 - 变更集 CLI。
¥Manually versioning and publishing packages in a monorepo can be tiresome. Luckily, there's a tool that makes things easy - the Changesets CLI.
我们推荐使用变更集,因为它使用起来直观易用,并且 - 就像 Turborepo 一样 - 适用于你已习惯的 monorepo 工具。
¥We recommend Changesets because it's intuitive to use, and - just like Turborepo - fits with the monorepo tools you're already used to.
一些替代方案如下:
¥Some alternatives are:
-
intuit/auto - 根据拉取请求中的语义版本标签生成版本
¥intuit/auto - Generate releases based on semantic version labels on pull requests
-
microsoft/beachball - 最阳光的语义版本缓冲器
¥microsoft/beachball - The Sunniest Semantic Version Bumper
发布
¥Publishing
软件包打包后,你可以将其发布到 npm 仓库。
¥Once your package has been bundled, you can then publish it to the npm registry.
我们建议你查看变更集文档。以下是我们推荐的阅读顺序:
¥We recommend taking a look at the Changesets docs. Here's our recommended reading order:
-
为什么使用变更集? - 一个介绍基础知识的简介。
¥Why use changesets? - an intro that takes you through the fundamentals.
-
如果你使用的是 GitHub,请考虑使用 变更集 GitHub 机器人 - 一个机器人,它会提醒你将变更集添加到 PR。
¥If you're using GitHub, consider using the Changeset GitHub bot - a bot to nudge you to add changesets to PR's.
-
你还应该考虑添加 变更集 GitHub 操作。 - 一个使发布变得极其简单的工具。
¥You should also consider adding the Changesets GitHub action - a tool which makes publishing extremely easy.
将变更集与 Turborepo 结合使用
¥Using Changesets with Turborepo
开始使用变更集后,你将可以使用三个有用的命令:
¥Once you've started using Changesets, you'll gain access to three useful commands:
将你的发布流程链接到 Turborepo 可以使你的部署组织更加简单快捷。
¥Linking your publishing flow into Turborepo can make organizing your deploy a lot simpler and faster.
我们建议将变更集配置为自动提交 changeset version
的变更。
¥Our recommendation is to configure Changesets to automatically commit changeset version
's changes
并将 publish-packages
脚本添加到你的根 package.json
中:
¥and add a publish-packages
script into your root package.json
:
如果你的包是公共的,请将变更集的 access
设置为 public
:
¥If your packages are public, set Changeset's access
to public
:
我们推荐使用 publish-packages
,这样它就不会与 npm 内置的 publish
脚本冲突。
¥We recommend publish-packages
so that it doesn't conflict with npm's
built-in publish
script.
这意味着当你运行 publish-packages
时,你的 monorepo 会被构建、linted、测试和发布。 - 你将受益于 Turborepo 的所有加速功能。
¥This means that when you run publish-packages
, your monorepo gets built, linted, tested and published - and you benefit from all of Turborepo's speedups.