缓存工作原理
在运行任何任务之前,Lerna 会计算其计算哈希值。只要计算哈希值相同,运行任务的输出就是相同的。
默认情况下,例如 lerna run test --scope=remixapp
的计算哈希值包括:
remixapp
及其依赖项的所有源文件- 相关的全局配置
- 外部依赖项的版本
- 用户提供的运行时值,如 Node 版本
- CLI 命令标志
这种行为是可自定义的。例如,lint 检查可能仅依赖于项目的源代码和全局配置。构建可以依赖于编译库的 dts 文件,而不是其源代码。
Lerna 计算任务的哈希值后,会检查是否之前运行过这个完全相同的计算。首先在本地检查,如果本地缓存丢失,且配置了远程缓存,则在远程检查。
如果 Lerna 找到了该计算,它会检索并重放。Lerna 将正确的文件放在正确的文件夹中,并打印终端输出。从用户的角度来看,命令运行了相同的操作,只是快得多。
如果 Lerna 没有找到对应的计算哈希值,Lerna 会运行任务,完成后将输出和终端日志存储在本地(如果配置了,也会存储在远程)。所有这些都是透明发生的,因此您不必担心。
尽管从概念上看这相当直接,但 Lerna 对此进行了优化,以提供良 好的用户体验。例如,Lerna:
- 捕获 stdout 和 stderr,确保重放的输出看起来相同,包括在 Windows 上。
- 通过记住文件在哪里重放来最小化 IO。
- 在处理大型任务图时仅显示相关输出。
- 提供排查缓存未命中的便利方法。以及许多其他优化。
随着工作空间的增长,任务图看起来更像这样:
所有这些优化对于使 Lerna 可用于任何非平凡的工作空间至关重要。只执行最少量的工作。其余的要么保持原样,要么从缓存中恢复。
源代码哈希输入
构建/测试应用程序或库的结果取决于该项目的源代码以及其直接或间接依赖的所有库的源代码。
默认情况下,Lerna 是保守的。例如,在运行 lerna run test --scope=remixapp
时,Lerna 将考虑 remixapp
目录中的所有文件以及 header
和 footer
目录(remixapp
的依赖项)中的所有文件。这会导致不必要的缓存未命中。例如,我们知道更改 footer
的规范文件不会改变上述测试命令的结果。
我们可以按以下方式定义更精确的配置:
注意:"{projectRoot}" 和 "{workspaceRoot}" 是任务运行器支持的特殊语法,在命令运行时将被适当地内部插值。因此,您不应将 "{projectRoot}" 或 "{workspaceRoot}" 替换为固定路径,因为这会使您的配置不够灵活。
{
"namedInputs": {
"default": ["{projectRoot}/**/*"],
"prod": ["!{projectRoot}/**/*.spec.tsx"]
},
"targetDefaults": {
"build": {
"inputs": ["prod", "^prod"]
},
"test": {
"inputs": ["default", "^prod", "{workspaceRoot}/jest.config.ts"]
}
}
}
使用此配置,构建脚本将仅考虑 remixapp
、header
和 footer
的非测试文件。测试脚本将考虑被测项目的所有源文件,以及其依赖项的非测试文件。测试脚本还将考虑工作空间根目录的 jest 配置文件。