从 TypeScript 3.8 及更高版本开始,Typescript 编译器公开了控制它如何监视文件和目录的配置。在此版本之前,配置需要使用仍然可用的环境变量。
¥As of TypeScript 3.8 and onward, the Typescript compiler exposes configuration which controls how it watches files and directories. Prior to this version, configuration required the use of environment variables which are still available.
背景
¥Background
编译器的 --watch
实现依赖于 Node 的 fs.watch
和 fs.watchFile
。这些方法中的每一种都有利有弊。
¥The --watch
implementation of the compiler relies on Node’s fs.watch
and fs.watchFile
. Each of these methods has pros and cons.
fs.watch
依靠文件系统事件来广播监视的文件和目录中的更改。该命令的实现依赖于操作系统且不可靠 - 在许多操作系统上,它不能按预期工作。此外,一些操作系统限制了可以同时存在的 watch 的数量(例如 Linux 的某些版本)。在大型代码库中大量使用 fs.watch
有可能超过这些限制并导致不良行为。但是,由于此实现依赖于基于事件的模型,因此 CPU 使用率相对较低。编译器通常使用 fs.watch
来监视目录(例如,编译器配置文件包含的源目录和模块解析失败的目录等)。TypeScript 使用这些来增加单个文件监视器中的潜在故障。但是,此策略有一个关键限制:Windows 和 macOS 支持目录的递归监视,但 Linux 不支持。这表明需要额外的文件和目录监视策略。
¥fs.watch
relies on file system events to broadcast changes in the watched files and directories. The implementation of this command is OS dependent and unreliable - on many operating systems, it does not work as expected. Additionally, some operating systems limit the number of watches which can exist simultaneously (e.g. some flavors of Linux). Heavy use of fs.watch
in large codebases has the potential to exceed these limits and result in undesirable behavior. However, because this implementation relies on an events-based model, CPU use is comparatively light. The compiler typically uses fs.watch
to watch directories (e.g. source directories included by compiler configuration files and directories in which module resolution failed, among others). TypeScript uses these to augment potential failures in individual file watchers. However, there is a key limitation of this strategy: recursive watching of directories is supported on Windows and macOS, but not on Linux. This suggested a need for additional strategies for file and directory watching.
fs.watchFile
使用轮询,因此会占用 CPU 周期。然而,fs.watchFile
是迄今为止最可靠的机制,可用于从感兴趣的文件和目录订阅事件。在这种策略下,TypeScript 编译器通常使用 fs.watchFile
来监视源文件、配置文件和根据引用语句显示丢失的文件。这意味着使用 fs.watchFile
时 CPU 使用率会更高的程度直接取决于在代码库中监视的文件数量。
¥fs.watchFile
uses polling and thus costs CPU cycles. However, fs.watchFile
is by far the most reliable mechanism available to subscribe to the events from files and directories of interest. Under this strategy, the TypeScript compiler typically uses fs.watchFile
to watch source files, config files, and files which appear missing based on reference statements. This means that the degree to which CPU usage will be higher when using fs.watchFile
depends directly on number of files watched in the codebase.
使用 tsconfig.json
配置文件监视
¥Configuring file watching using a tsconfig.json
配置监视行为的建议方法是通过 tsconfig.json
的新 watchOptions
部分。我们在下面提供了一个示例配置。有关可用设置的详细说明,请参阅以下部分。
¥The suggested method of configuring watch behavior is through the new watchOptions
section of tsconfig.json
. We provide an example configuration below. See the following section for detailed descriptions of the settings available.
{// 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 的发行说明。
¥For further details, see the release notes for Typescript 3.8.
使用环境变量 TSC_WATCHFILE
配置文件监视
¥Configuring file watching using environment variable 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
配置目录监视
¥Configuring directory watching using environment variable TSC_WATCHDIRECTORY
对于原生不允许递归目录监视(即非 macOS 和 Windows 操作系统)的平台上的目录监视,通过使用 TSC_WATCHDIRECTORY
选择的不同选项为每个子目录递归创建目录监视程序来支持。
¥For directory watches on platforms which don’t natively allow recursive directory watching (i.e. non macOS and Windows operating systems) is supported through recursively creating directory watchers for each child directory using different options selected by TSC_WATCHDIRECTORY
.
注意:在支持原生递归目录监视的平台上,忽略 TSC_WATCHDIRECTORY
的值。
¥NOTE: On platforms which support native recursive directory watching, the value of TSC_WATCHDIRECTORY
is ignored.
选项 | 描述 |
---|---|
RecursiveDirectoryUsingFsWatchFile |
使用 fs.watchFile 查看包含的目录和子目录。 |
RecursiveDirectoryUsingDynamicPriorityPolling |
使用动态轮询队列来轮询对包含的目录和子目录的更改。 |
默认值(未指定值) | 使用 fs.watch 查看包含的目录和子目录。 |