vscode.workspace.createFileSystemWatcher可监听文件创建、删除、重命名和内容修改,但不区分修改来源;需注意glob递归限制、WSL2下动态目录漏监等问题。

vscode.workspace.createFileSystemWatcher 能监听哪些变更
它能捕获文件创建、删除、重命名和内容修改四类事件,但**不区分修改来源**(编辑器内保存 or 外部工具写入)。监听路径用 glob 模式(如 **/*.ts),注意它默认不递归监听子目录里的新创建目录——除非你显式加上 ** 或启用 recursive 选项(取决于底层 OS 支持)。
常见误判点:监听 src/** 时,如果后续动态生成了 src/generated/ 目录,部分系统(尤其是 WSL2)可能漏掉该目录下首次创建的文件。稳妥做法是监听更宽泛的 src/**/* 或直接用 ** 配合 files.watcherExclude 过滤。
监听 .git/HEAD 实现分支切换检测
Git 分支切换本质是修改 .git/HEAD 文件内容(从 ref: refs/heads/main 变为 ref: refs/heads/dev)。这个文件体积小、更新频繁、语义明确,适合做轻量级监听。
- 用
vscode.workspace.createFileSystemWatcher('.git/HEAD')创建 watcher - 在
onDidChange回调里读取新内容,解析出当前分支名(正则匹配refs/heads/(.+)) - 避免在
onDidCreate里处理——HEAD 不会被“创建”,只会被覆盖写入 - 记得在扩展停用时调用
watcher.dispose(),否则残留监听器会引发内存泄漏
chokidar 为什么比原生 watcher 更可靠
VSCode 原生 createFileSystemWatcher 在跨平台一致性上有限制:Windows 上对符号链接支持弱,WSL2 下对挂载路径事件丢失率高,macOS 上偶尔合并多次修改为单次事件。而 chokidar 是 Node.js 生态事实标准,它自动 fallback 到轮询(usePolling: true)当原生 API 失效时,且能精确控制事件去抖(awaitWriteFinish)。
实际使用建议:
- 安装:
npm install chokidar - 监听时显式禁用 VSCode 自身 watcher:
"files.watcherExclude": { "**": true },防止双重监听冲突 - 关键路径(如配置、密钥文件)用
chokidar.watch(path, { usePolling: true, interval: 1000 })确保不丢事件
监听后触发逻辑必须防重复执行
同一个文件保存操作,在某些场景下可能触发多次 onDidChange(例如 ESLint 自动修复 + Prettier 格式化先后写入)。直接在回调里调用 heavy logic 会导致任务堆积或状态错乱。
推荐做法:
- 用节流(throttle)包装处理函数,例如 Lodash 的
throttle(fn, 500) - 对同一文件维护一个
pendingMap: Map,每次变更先 clearTimeout 再 setTimeout - 若逻辑涉及 UI 更新(如状态栏文字),务必检查
vscode.window.state.focused,非聚焦窗口时不刷新,减少干扰
真正难的是事件边界控制——比如监听 package.json 变更后要重载依赖树,但用户正在输入中,你得等他停顿 300ms 再执行;又比如监听日志目录,得跳过 .tmp 和 .swp 类临时文件,这些细节不写死在 glob 里,就只能靠运行时过滤。











