运行故障排除
与大多数工具一样,理解 Turborepo 为什么没有按预期工作可能会让人沮丧。本页介绍了一些在使用 turbo
CLI 时进行调试的工具,以及您可能会遇到的一些常见问题。
启用详细日志
作为开发人员,我们拥有的最佳调试工具是日志。您可以使用 --verbosity
标志提高日志级别。结合 从源代码构建,这可以成为查看幕后情况的一种强大而灵活的方式。
检查运行摘要
--summarize 标志会生成并保存有关您的 turbo run
的元数据,作为 .turbo/runs
中的 JSON 文件。您可以使用它来比较后续运行、检查缓存工件的内容以及任务的哈希输入。
检查您的配置
任务配置
您可以使用 Turborepo 入门,配置最少 - 这是人们喜欢 Turborepo 的原因之一!但是,当您省略配置时,Turborepo 在内部会回退到智能默认值。此外,当在 Monorepo 中使用 工作区配置 时,理解 Turborepo 如何解释您的 turbo.json
可能很令人困惑。您可以使用 --dry
或 --dry=json
来获取任何任务的“已解析”任务配置。例如
turbo run build --dry=json
在输出中查找 resolvedTaskConfiguration
键。
用户配置
当您将您的存储库链接到 Vercel 时,Turborepo 会将配置存储在两个位置
- 您的 Vercel 团队信息存储在
.turbo/config.json
中。您可以检查此文件以查看其中可能还有哪些内容! - 身份验证令牌存储在
~/Library/Application\ Support/turborepo/config.json
中。
检查缓存
当 turborepo 运行一个已配置 outputs
的任务时,它会将这些输出以及该任务的日志缓存到 node_modules/.cache/turbo/
中。这些工件使用 tar
压缩,但您可以解压缩并查看它们的内容。
从源代码构建
JavaScript 代码库的优势之一是你可以打开 node_modules/
并编辑正在运行的代码。这在 turbo
中是不可能的,因为可运行代码是编译后的二进制文件,你无法直接编辑它。但由于代码库是开源的,你始终可以获取源代码,修改它,并在本地构建它。本手册的大部分内容可以在 贡献指南 (在新标签页中打开) 中找到,即使你没有打算贡献,也可以使用这些说明。
- 从
vercel/turbo
(在新标签页中打开) 克隆 git 仓库 cd cli
- 进行任何更改(例如,添加更多日志记录)
- 运行
make
- 在 你的 项目中,使用
/:path/:to/:turbo/target/debug/turbo
而不是全局 turbo 或项目中安装的turbo
版本。
常见问题
嵌套工作区
Turborepo 不支持嵌套工作区。因此,如果你有一个包含另一个工作区的工作区,你可能会看到意外的行为。我们建议你将工作区结构扁平化以避免此问题。
根依赖项
如果你在你的单仓库中定义了一个包,该包被单仓库中的其他几个包使用,比如一个标准的 ESLint 配置,你可能会想在你的单仓库根目录的 package.json
中将其声明为根依赖项。这使你可以在整个单仓库中使用该依赖项,而无需在每个包的 package.json
中声明它。但是,这会导致意外的缓存命中,因为 Turbo 不会 将根内部依赖项(即在你的单仓库的 package.json
(根)中声明并在你的单仓库(内部)中实现的依赖项)包含在它的缓存签名中。因此,如果根内部依赖项发生更改,其他任何包都不会被重新构建。
为了解决这个问题,始终将包的内部依赖项显式添加到其 package.json
中。你可以在 这里 找到关于如何执行此操作的说明。
.turbo
目录
Turbo 背后的一个 核心概念 是,当声明的输入发生更改时,该任务的缓存输出将失效。作为运行任何任务的一部分,Turborepo 会创建以下目录
- 在你的仓库根目录中的
.turbo
- 如果你的项目是单仓库,则每个工作区中都有一个
.turbo
目录(例如apps/my-app/.turbo/
) - 在
node_modules/.cache
中的turbo
目录
由于前两个目录默认情况下不会被 git 忽略,你可能会遇到一个问题,即你运行同一个任务两次,但会得到缓存丢失,即使你没有进行任何更改,因为生成的 .turbo
目录被包含为任务的 输入,并使缓存失效。为了避免这个问题,请将 .turbo
添加到你的 .gitignore
文件中。或者,你也可以限制你的 inputs
配置,以便 .turbo
不包含在缓存输入中。
常见问题
我没有看到任何缓存命中
一般来说,你应该期望当你连续两次运行 turbo run
时,你应该在第二次运行时获得缓存命中。如果这种情况没有发生,请使用 --summarize
标志 再次运行这两个构建,并将生成的运行摘要进行比较。在大多数情况下,比较应该显示为什么第二次运行没有获得缓存命中。
你也可以询问
-
在构建过程中是否生成了任何未签入 git 的源代码?
这将更改 Turborepo 用于存储构建输出的指纹。
-
缓存 输出 是否在你的 Turborepo 管道 中正确指定?
管道设置不会被继承或合并,因此需要在 特定工作区任务 中重新指定(例如,
web#build
不会 继承来自build
的管道设置)。 -
启用详细模式 以查看哪些环境变量包含在哈希中。
我看到了缓存命中,但我的构建已损坏
-
缓存输出是否在你的 Turborepo 管道 中正确指定?
管道设置不会被继承或合并,因此需要在 特定工作区任务 中重新指定(例如,
web#build
不会 继承来自build
的管道设置)。
我的构建正在缓存错误的环境变量
-
启用详细模式 以查看哪些环境变量包含在哈希中。
常见单仓库问题
我的依赖项没有被正确构建
-
你是否在构建应用程序之前正确地捆绑和转译了依赖项?
例如,像
tsc
、tsup
、esbuild
、babel
和swc
这样的库将把较新的 JavaScript 功能转换回“纯”JavaScript。如果你使用的是 Next.js,你可能正在使用
transpilePackages
。确保你在next.config.js
中添加了依赖项的名称 (示例 (在新标签页中打开))。 -
你是否在依赖项的
package.json
中列出了files
以指向正确的文件?
我的类型没有被找到
-
您是否在依赖项的
package.json
中指定了types
或typing
来指向.d.ts
文件? -
您是否修改或设置了自定义的
tsconfig.json
paths
?- 它们是否具有适合您应用程序的正确文件夹结构?
- 它们是否为元框架、捆绑器或转译工具正确配置?