Add an ignore/exclude option to --watch (fixes infinite restart loop when a watched process writes+imports a file, e.g. Vite createServer)
还没有人认领这个 Issue。
- 主要语言
- JavaScript
- 星标
- 122k
- 派生
- 37.3k
- 平均合并
- 4 天 2 小时
- 30 天内合并 PR
- 283
描述
What is the problem this feature will solve?
node --watch enters an infinite restart loop when the watched process itself writes a file and then dynamically imports it during startup. The watcher adds the freshly-written, now-imported file to its watch set, sees it as "changed," and restarts — which re-runs the same write-and-import, restarting again, forever.
The most common real-world trigger is starting a Vite dev server in middleware mode under node --watch: Vite's config loader writes a temporary config file and await import()s it during createServer(). There is currently no way to exclude that file (or node_modules, or any generated/temp path) from --watch, so the loop cannot be worked around with native flags.
Today node --watch only offers --watch, --watch-path, and --watch-preserve-output. There is no ignore/exclude option. (#45467 is the inverse request — adding paths to watch.)
Minimal reproduction
In any project with vite installed, create repro.mts:
import { createServer } from "vite";
const v = await createServer({ appType: "custom", server: { middlewareMode: true } });
console.log("VITE_UP", typeof v.middlewares);
setInterval(() => {}, 1000);
Run:
node --watch repro.mts
Observed
VITE_UP function
Restarting 'repro.mts'
VITE_UP function
Restarting 'repro.mts'
... (repeats indefinitely)
Reproduced on every version tested (darwin arm64), ~34–35 Restarting cycles in ~15 seconds:
| Node version | Result |
|---|---|
| 22.23.1 | loops (35 boots / 35 restarts) |
| 24.13.1 (latest LTS) | loops (34 boots / 34 restarts) |
| 23.x | loops (per linked Vite issue) |
Expected
The process boots once and stays up until a source file the developer actually edits changes — i.e. files written and imported by the process itself during startup should not be able to trigger a restart, or there should be a way to exclude them.
Root cause
Per the analysis in vitejs/vite#19854, Vite's config loading writes a temp file and immediately dynamic-imports it (return (await import(pathToFileURL(tempFileName).href)).default). Inserting a delay between the write and the import stops the loop, confirming a race between the process's own write+import and --watch's file monitoring. Because --watch watches every imported file and has no exclude mechanism, the generated file becomes a restart trigger.
What is the feature you are proposing to solve the problem?
An ignore/exclude option for watch mode, e.g.:
node --watch --watch-exclude='**/node_modules/**' --watch-exclude='**/.vite-temp-*' app.mts
(name/spelling open — --watch-exclude or --watch-ignore, glob-based, repeatable). This would let developers exclude node_modules, build caches, and temp/generated files from triggering restarts, which resolves this loop and matches what every userland watcher (nodemon, tsx, chokidar-based tools) already provides.
Optionally/additionally: do not let files written by the watched process after startup began count as external changes for the initial run.
What alternatives have you considered?
--watch-path— scopes what is watched but cannot exclude a sub-path or generated file from an otherwise-watched tree, so it doesn't fix this.- Userland watchers (
tsx watch,nodemon) — these do not loop on the identical reproduction because they watch only the static import graph and/or support ignore globs. This is the gap relative to native--watch.
Related issues / downstream reports
- vitejs/vite#19854 — Node
--watch+createServer()infinite reload loop (closed as "not planned"; no determination of whether it's a Vite or Node issue). - nubjs/nub#204 — same loop via
nub watch, which wraps Node's native--watch(identicalRestarting '<file>'output).
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 node --watch 入口点开始,运行使用 createServer() 的最小 Vite 复现,以观察重启循环。确定受支持的 exclude 或 ignore 语义,然后验证可重复的 glob 选项能够防止生成文件或临时文件触发重启,同时源文件的更改仍会触发重启。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript, node.js
- 领域
- cli, tooling
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 45/100