从 TypeScript 3.8 开始,TypeScript 编译器提供了用于控制其监视文件和目录方式的配置。在此版本之前,配置需要使用环境变量,这些环境变量目前仍然可用。
背景
编译器的 --watch 实现依赖于 Node 的 fs.watch 和 fs.watchFile。这两种方法各有优缺点。
fs.watch 依赖文件系统事件来广播被监视的文件和目录中的变化。该命令的实现依赖于操作系统,而且并不可靠——在许多操作系统上,它并不能按预期工作。此外,某些操作系统会限制可同时存在的监视数量(例如某些版本的 Linux)。在大型代码库中大量使用 fs.watch 有可能超出这些限制,导致不理想的行为。不过,由于这种实现基于事件模型,CPU 占用相对较轻。编译器通常使用 fs.watch 来监视目录(例如编译器配置文件中包含的源目录,以及模块解析失败的目录等)。TypeScript 使用它们来弥补单个文件监视器可能出现的故障。然而,这种策略有一个关键限制:对目录的递归监视在 Windows 和 macOS 上受支持,但在 Linux 上不受支持。这表明需要为文件和目录监视提供额外的策略。
fs.watchFile 使用轮询,因此会消耗 CPU 周期。不过,fs.watchFile 目前是订阅感兴趣的文件和目录事件最可靠的机制。在这种策略下,TypeScript 编译器通常使用 fs.watchFile 来监视源文件、配置文件,以及根据引用语句判断为缺失的文件。这意味着使用 fs.watchFile 时 CPU 占用升高的程度,直接取决于代码库中被监视的文件数量。
使用 tsconfig.json 配置文件监视
配置监视行为的推荐方法是通过 tsconfig.json 中新增的 watchOptions 部分。下面提供一个示例配置。各项可用设置的详细说明见下一节。
{// Some typical compiler options"": {"": "es2020","": "node"// ...},// NEW: Options for file/directory watching"watchOptions": {// Use native file system events for files and directories"": "useFsEvents","": "useFsEvents",// Poll files for updates more frequently// when they're updated a lot."": "dynamicPriority",// Don't coalesce watch notification"": true,// Finally, two additional settings for reducing the amount of possible// files to track work from these directories"": ["**/node_modules", "_build"],"": ["build/fileWhichChangesOften.ts"]}}
更多详情请参阅 TypeScript 3.8 的发行说明。
使用环境变量 TSC_WATCHFILE 配置文件监视
| 选项 | 描述 |
|---|---|
PriorityPollingInterval |
使用 fs.watchFile,但对源文件、配置文件和缺失文件使用不同的轮询间隔 |
DynamicPriorityPolling |
使用动态队列,频繁修改的文件以较短的间隔轮询,未变化的文件轮询频率较低 |
UseFsEvents |
使用 fs.watch。在限制活动监视数量的操作系统上,当监视器创建失败时回退到 fs.watchFile。 |
UseFsEventsWithFallbackDynamicPolling |
使用 fs.watch。在限制活动监视数量的操作系统上,回退到动态轮询队列(如 DynamicPriorityPolling 中所述) |
UseFsEventsOnParentDirectory |
在被包含文件的父目录上使用 fs.watch(这是一种折中方案,CPU 占用比纯 fs.watchFile 更低,但准确性可能也较低)。 |
| 默认值(未指定值) | 如果环境变量 TSC_NONPOLLING_WATCHER 设为 true,则使用 UseFsEventsOnParentDirectory。否则,使用 fs.watchFile 监视文件,并将任意文件的超时设为 250ms。 |
使用环境变量 TSC_WATCHDIRECTORY 配置目录监视
对于本身不支持递归目录监视的平台(即非 macOS 和 Windows 操作系统),可以通过使用由 TSC_WATCHDIRECTORY 选择的不同选项,为每个子目录递归创建目录监视器来支持目录监视。
注意:在支持原生递归目录监视的平台上,TSC_WATCHDIRECTORY 的值会被忽略。
| 选项 | 描述 |
|---|---|
RecursiveDirectoryUsingFsWatchFile |
使用 fs.watchFile 监视被包含的目录和子目录。 |
RecursiveDirectoryUsingDynamicPriorityPolling |
使用动态轮询队列轮询被包含的目录和子目录的变化。 |
| 默认值(未指定值) | 使用 fs.watch 监视被包含的目录和子目录。 |