如果你是那种一个仓库里堆着前端、后端、CLI 工具、文档和一个公共资源目录的人,肯定遭遇过这样的早晨:顺手按下 Ctrl/Cmd+Shift+F 搜一个变量名,结果几千条结果刷屏,匹配大多来自 node_modules、dist、coverage、vendor 这些“永远不想搜到”的地方。虽然 VS Code 搜索面板也有 exclude 输入框,但临时填一次还可以,换一台电脑或者换一个 workspace 就全忘了,根本谈不上“可复现”。
这段时间我集中把所有项目的搜索范围整理了一遍,核心诉求只有一个:VS Code 单独配置每个文件夹的搜索路径,做到精准控制。这里说的“文件夹”,既可以是单仓库里的 src、docs、build 等子目录,也可以是多根工作区里每个独立项目目录。把这件事做顺之后,搜索速度和结果准确度都有非常明显的提升,而且设置随着.vscode/settings.json、.code-workspace文件走,团队协作时也能保证每个人经验一致。
这篇内容我不打算只贴配置,会把 VS Code 搜索底层的 glob 规则、设置优先级、include/exclude 的互相作用一并讲清楚,再给几个实际场景的完整配置和排查经验。文章比较长,但每段都是能落地的,直接照着抄就行。
1. 搜索范围的底层逻辑:路径是怎么被“算”出来的
1.1 一次搜索的范围等于“根文件夹减去排除项,再加上包含项”
VS Code 搜索功能底层用的是 ripgrep,所以你在设置里写的几乎都是 glob,而不是简单的绝对路径。搜索范围大致是这个公式:
可搜索范围 = 所有根文件夹 - 排除项(exclude) + 包含项(include)默认情况下,VS Code 会搜索当前打开的所有根文件夹,然后按 rules 逐步收紧或放开。理解这一点很重要:很多人以为在设置里加几个排除路径就完事了,但真正“精准”的工具箱应该是包含项、排除项、忽略文件三个维度配合的。
- 排除项:比如
search.exclude,把不想搜的文件路径从结果中去掉。 - 包含项:搜索面板里的
files to include,只留指定的路径模式,相当于给搜索先画个圈。 - 忽略文件:
.gitignore、.ignore等,默认会被 ripgrep 尊重,甚至不进入搜索索引。
所以“给每个文件夹配置搜索路径”这件事,本质上就是管理好这三个维度,并让它们作用在正确的范围上。
1.2 设置优先级:不是所有 exclude 都平级
很多人在多根工作区里排除了半天,发现某个文件夹还是“不听使唤”,多半是没有搞清楚设置层级。VS Code 的设置从上到下大致是这样的:
- 默认设置
- 用户设置
- 远程设置(如果开了远程开发)
- 工作区设置(
.code-workspace里的 settings 块) - 文件夹设置(每个根文件夹对应的
.vscode/settings.json)
后一层的设置会覆盖前一层。注意,在设置编辑器里看到的“作用范围”并不是摆设,它决定了你这次改动到底存到哪个层。如果某个文件夹有自己的.vscode/settings.json,那就需要在那个文件里设置,而不是只放在公共 workspace 设置里。
1.3 files.exclude 和 search.exclude 别搞混
这两个设置看起来相似,实际作用完全不同。我见过大量同学只改了 files.exclude,发现搜索结果里文件照样出现,然后开始怀疑配置没生效,其实只是改错了地方。
| 设置项 | 作用 | 典型场景 |
|---|---|---|
files.exclude | 从资源管理器里隐藏文件/文件夹 | 不想让同事看到无关目录,但搜索时希望仍能命中 |
search.exclude | 从搜索结果里排除文件/文件夹 | 不想搜到构建产物、缓存、生成的临时文件 |
search.useIgnoreFiles | 是否遵循.gitignore和.ignore文件 | 控制受版本控制忽略的内容是否进入搜索 |
优先级方面,如果同一个 glob 同时出现在files.exclude和search.exclude里,搜索时会以search.exclude为准。反过来,files.exclude不会自动变成搜索排除项。
1.4 简单过一遍 glob:精准控制的语法基础
既然核心是路径模式,就必须先掌握几个常用 glob 写法:
*:匹配单层路径的一段,不跨/**:跨任意多层目录?:匹配单个字符{a,b}:匹配 a 或 b 两种路径!:表示取反
举例来说:
{ "search.exclude": { "**/node_modules": true, "src/*.js": true, "dist/**/*.map": true } }**/node_modules匹配任意层级下的 node_modules 目录,比node_modules/**更通用。src/*.js只匹配 src 直接子目录下的 .js 文件,不匹配src/foo/bar.js。dist/**/*.map会匹配 dist 下任意深度的.map文件。
越是复杂的项目,越建议先用这种模式试出最合适的范围,再落到配置文件里,别直接一上来就写一堆大而全的规则。
2. 单文件夹项目:把搜索锁在指定路径
2.1 临时搜一个文件夹:直接在 Files to include 里写
如果只是想快速看一下某个目录下有哪些目标文件,不需要改任何配置。搜索面板最上方有files to include输入框,填路径模式即可。
搜索目标:只有src/pages下的文件,可以写:
src/pages/**如果想同时搜多个目录,用空格分隔:
src/pages/** src/components/**这套方式很适合临时排查,特别是调试问题上时不想让周围目录参与命中。但它的缺点也很明显:不持久,关了搜索历史基本作废。真正长期的项目规则不要放这里,而是放到search.exclude里。
2.2 持久规则:在项目根目录写 search.exclude
单文件夹项目里,所有搜索规则都放在项目根目录的.vscode/settings.json里。这是我们常说的“项目级配置”,会跟代码一起提交,团队其他成员打开项目时自动生效。
举个常见的前端项目结构:
app/ src/ components/ pages/ dist/ node_modules/ docs/ generated/ content/我希望搜索时永远不看到node_modules、dist、docs/generated。打开.vscode/settings.json,写入:
{ "search.exclude": { "**/node_modules": true, "app/dist/**": true, "docs/generated/**": true } }设置保存后,下一次搜索会自动套用。如果想在资源管理器里也隐藏这些目录,那再把同样的模式加到files.exclude。但这种情况下要看清楚:两者是独立的,不要以为改了files.exclude就能净化搜索结果。
2.3 利用右键菜单快速生成排除规则
不想手写 glob 时,另一个很舒服的方式是直接右键搜索结果里的某个文件或文件夹。
右键一个命中的文件,选择“排除”,VS Code 会自动帮你写好对应的search.exclude规则。
用这种方式生成的 glob 通常比较保守,比如:
{ "search.exclude": { "**/coverage": true } }但它至少能保证:下次再搜时,这个路径不会再刷屏。比手工输入少翻车。当然,它生成的是“排除整个文件夹”的语义,想做到更细的精确控制,还是得回到设置文件里手动改。
提示:我实际用的时候,先临时用 Files to include 锁定范围,验证 glob 是否命中目标,再把这个模式固化到
search.exclude。这样写出来的规则基本不会出幺蛾子。
2.4 单文件夹场景常见的误区
单文件夹项目最容易犯的错是:把规则写在用户设置里,并没有跟随项目走。用户设置是全局的,换一个项目后排除规则仍然存在,可能导致新项目某些目录莫名搜不到。所以只要规则和具体业务相关,都应该写进项目的.vscode/settings.json,而不是用户设置。
另外,search.exclude里的 glob 是相对于根文件夹的。如果项目根目录是my-project,你写my-project/src/**就不太合适,因为 VS Code 在执行这批规则时,看到的路径已经是相对my-project的src/**。模式前缀带了一层越级目录,结果往往是一场空。
3. 多根工作区:让每个文件夹真正“各自为政”
3.1 为什么单根目录不够用
很多 monorepo 项目虽然打开时只选了一个根目录,但里面几十个子项目各有各的产物目录、测试目录和旧代码。根目录的search.exclude只能写一套全局规则,很难兼顾每个子目录的需求。
这种情况下,最正规的姿势是把子项目们作为多根工作区打开。这也就是标题里“单独配置每个文件夹”的核心场景:不是靠同一套规则去通配所有目录,而是让每个文件夹都有自己的.vscode/settings.json。
例如:
workspace/ packages/ api-server/ web-app/ shared/普通模式下只能写:
{ "search.exclude": { "**/node_modules": true, "packages/api-server/build/**": true, "packages/web-app/out/**": true } }这没问题,但如果你包再多一点,规则会越来越长,而且一旦涉及到某个包的 snapshot、fixtures、throw-away 目录,公共规则就会变得很难维护。
3.2 转成多根工作区的具体步骤
- 打开 VS Code,执行“文件 → 将文件夹添加到工作区”,把
packages/api-server、packages/web-app、packages/shared都添加进去。 - 执行命令面板里的“将工作区另存为”,生成一个
.code-workspace文件,把多根工作区配置固化下来。 - 每个包目录下建立自己的
.vscode/settings.json。
.code-workspace里可以放公共规则,比如**/node_modules这种几乎所有包都绕不开的目录:
{ "folders": [ { "path": "packages/api-server" }, { "path": "packages/web-app" }, { "path": "packages/shared" } ], "settings": { "search.exclude": { "**/node_modules": true, "**/*.log": true } } }然后在packages/api-server/.vscode/settings.json里写 API 服务的独有规则:
{ "search.exclude": { "build/**": true, "migrations/**": true, "generated_proto/**": true } }在packages/web-app/.vscode/settings.json里写前端的独有规则:
{ "search.exclude": { "out/**": true, "public/vendor_min/**": true } }这样做的效果很直观:搜索api-server下的函数时,不会误入它的 proto 生成文件;搜索前端状态管理代码时,又不用整天手动去排除 vendor_min 这种压缩产物。
3.3 用设置编辑器为指定文件夹改配置
如果你不想手工打开每个.vscode/settings.json,也可以利用设置编辑器的作用范围下拉框。
当工作区是多根工作区时,设置编辑器的顶部会出现一个“文件夹”范围的选项。选择一个文件夹后,再把search.exclude里对应的排除模式加上去,VS Code 会自动把这个配置写入该文件夹自己的.vscode/settings.json中。
这点我也特别建议新人用:至少不会出现“我不知道这个设置到底算谁的”这种迷惑。
3.4 多根工作区优先级的一个坑
多根工作区的优先级顺序我说过一点,但实际操作中要注意:某个文件夹级的search.exclude会覆盖该文件夹所用的上层同名设置,而不是像“合并数组”一样混合起来。
举个例子,如果共享.code-workspace里定义了:
"search.exclude": { "**/node_modules": true }同时packages/web-app/.vscode/settings.json里定义了:
"search.exclude": { "out/**": true }那么 web-app 这个根文件夹搜索时,可能存在只有out/**被应用、公共的**/node_modules反而不生效的情况。具体会不会做到对象级合并,跟 VS Code 的版本和行为有关,我不建议依赖这种合并。要稳妥的话,就把公共规则在当前文件夹的配置里再写一遍。
我在实际工作中就把这类公共规则抽成一个片段,每个新建的包目录都复制一份底部基础段,再在上面加独有规则:
{ "search.exclude": { "**/node_modules": true, "**/.git": true, "**/.cache/**": true, "out/**": true, "build/**": true } }不要嫌重复,配置文件最怕的是隐式行为。
4. 高级组合:把 include、exclude 和通配用到极致
4.1 让某个文件夹“不参与任何搜索”
多根工作区里,有些文件夹可能是归档性质,平时根本不需要出现在搜索结果里。这时候与其一个个排除目录,不如直接在它自己的.vscode/settings.json里写:
{ "search.exclude": { "**": true } }**表示当前根文件夹下的所有路径,整个文件夹就从搜索范围内消失了。之后不管怎么搜,它都不会再上榜。这个思路非常适合用在旧项目、还原包、大型演示 Demo 上。
4.2 include 和 exclude 交叉使用
有些场景不是“排除一个固定目录”,而是“我只要这个目录,其他都别出现”。
单根项目里,可以用 Files to include 输入:
src/**但这只能保证搜索结果里“多出” src 的匹配,如果另外几个文件夹也有同名文件名,还是会被一起搜进来。想彻底隔离,就得配合 exclude 或目录级屏蔽。
我的习惯是这样的:核心目录用 include 圈起来,噪声目录用 exclude 兜底。只留下一个比如codegen/**这样目录时:
codegen/**然后在search.exclude里保留:
{ "search.exclude": { "**/node_modules": true, "**/.cache/**": true } }这样 include 负责“抓主流”,exclude 负责“压残余”,准确率会高很多。
4.3 利用灰名单模式:把一类文件全部拦掉
精确控制不只是针对目录,也可以针对文件类型。比如项目里的快照测试文件、编译压缩文件、日志文件,往往不参与日常搜索:
{ "search.exclude": { "**/*.snap": true, "**/*.min.js": true, "**/*.log": true, "**/__snapshots__/**": true, "**/*.d.ts": true } }其中**/*.d.ts建议慎重,某些大型 TS 项目里.d.ts文件还需用于查类型定义,如果排得太彻底,你会搜不到第三方类型声明。这个要根据自己的项目权衡。
4.4 让某些被 .gitignore 忽略的文件也能被搜到
默认情况下.gitignore里面的文件不会进搜索,这意味着你无法在一个 git 仓库里通过搜索查看本地临时文件的内容。如果确实需要,可以在对应文件夹的设置里打开:
{ "search.useIgnoreFiles": false }但这会明显拉低搜索速度,因为原本被忽略的文件里可能有数据库 dump、本地上传资源等大文件。我个人不太建议全局关,真要找工作区里某个被忽略文件,直接用文件资源管理器定位更稳。
4.5 按文件夹控制大小写敏感性
搜索大小写这个看起来不是“路径”问题,但在多语言项目里也容易被坑。单根项目可以开search.smartCase,多根工作区里不同文件夹如果项目语言不同,可以在各自.vscode/settings.json独立配置:
{ "search.smartCase": true }这个不属于路径排除的核心,但它能避免“我搜UserID,结果把userid也捞出来”这类误伤,对精准控制是一个很好的补充。
5. 常见问题排查与避坑经验
5.1 明明排除了,搜索结果里还是会出现
先把files.exclude和search.exclude分开判断。你改的是哪一个?如果只改了files.exclude,搜索当然不会变。正确做法是看看是不是应该配置search.exclude。
另外,如果你在某个文件夹设置里写了search.exclude,但这个文件夹并不是根文件夹,而是根文件夹下的子目录,那 VS Code 不会读取它。.vscode/settings.json只在“被打开的工作区根文件夹”下生效,子目录里的.vscode/settings.json不会自动成为多根工作区配置的一部分。
如果你确实想让仓库里的某个子目录拥有独立的搜索设置,唯一干净的做法是把它作为独立根文件夹添加进工作区,哪怕它们物理上还在同一个父目录里。
5.2 设置层级导致规则失效
排查思路主要看三层:
- 用户设置里是不是有个很宽的
search.exclude? - 工作区
.code-workspace里是不是有覆盖行为? - 当前文件夹的
.vscode/settings.json是不是真的被读取到了?
最常见的失败场景是多根工作区的某个文件夹实际并没有自己的.vscode/settings.json,结果你以为改了它,实际改到的是共享工作区设置,而共享设置又覆盖不到其他层的某条 include 规则。
5.3 glob 写对了,但路径前缀不对
我见过不少人把 Windows 和 mac 风格路径混着写,比如用反斜杠分隔目录。搜索 glob 在 VS Code 里统一按/处理。写:
out/views/**而不是:
out\views\**第二种看起来在资源管理器里很合理,但搜索根本不会按照它执行。
5.4 临时只搜一个文件夹:Find in Folder
如果只是临时要精确到一个文件夹,其实不需要改配置文件。在资源管理器里右键目标文件夹,选“在文件夹中查找”,VS Code 会自动带上对应的 include 模式。
这个操作我也会经常写在团队规范里,因为对同事来说门槛最低,环境一致性最好。唯一需要注意的是:它会记住最近一次搜索历史中的包含项,下次普通搜索时如果没清空,可能还是会被圈住。所以我搜完临时文件后习惯把 Files to include 清空。
5.5 搜索结果太慢,先看是不是被 include 拽进了大目录
有个很容易忽略的情况:你虽然写了排除,但 Files to include 里有个宽泛模式,比如:
./或
**/*这基本等于把所有文件都拉进来搜索。此时排除再多目录也救不回车速。我一般会确认一下 include 框里是否残留着上次随手输入的东西,尤其是全局搜索时。
写在最后的一些习惯
最后说一个我自己的操作习惯:我不会在单个大型项目里堆积越来越多的search.exclude,而是会用多根工作区来拆分。新加入一个业务模块时,先建.vscode/settings.json,基础排除规则直接从团队公共模板复制,再留下两行注释说明这个目录里最关键的搜索禁区是什么。这样每个文件夹的搜索路径都是“自我声明”的,而不是靠一个超级大 codeless 到全局去猜。
还有些人问要不要装额外扩展来控制搜索,其实不用。VS Code 原生这套 glob + 多层设置已经足够应付绝大多数仓库。重点还是把规则放对层级,让每个文件夹说清楚自己想搜什么、不想搜什么,你就能从海量结果里解放出来。