ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Gulp 5 Glob 匹配完全指南:从 `*`、`**` 到 `!` 的路径模式语法与工程实践

Gulp 5 Glob 匹配完全指南:从 `*`、`**` 到 `!` 的路径模式语法与工程实践 Gulp 5 Glob 匹配完全指南从*、**到!的路径模式语法与工程实践【免费下载链接】gulpA toolkit to automate enhance your workflow项目地址: https://gitcode.com/gh_mirrors/gu/gulp本文是 gulp 官方 Getting Started 系列中 Explaining Globs 的深度扩展系统讲解 glob 的语法要素段与分隔符、*、**、!、src()对 glob 的消费规则以及 v5 中负向 glob、有序 glob、重叠 glob 的行为变迁。读完本文你将能写出准确、高效、跨平台可用的 gulp 文件匹配模式并理解其背后的底层实现与测试证据。glob 是什么定位文件的语言glob 是由字面量字符和通配符字符组成的字符串用于匹配文件路径。而 globbing 则是使用一个或多个 glob 在文件系统上定位文件的行为。在 gulp 中glob 是构建管道的起点——你用它告诉 gulp把哪些文件交给任务处理。gulp 的src()方法接受单个 glob 字符串或glob 数组来决定你的管道将操作哪些文件const { src, dest } require(gulp); // 单个 glob src(src/*.js) // glob 数组 src([src/**/*.js, !src/vendor/**])两个关键约束需要牢记至少必须有一个匹配。如果所有 glob 都没有匹配到任何文件src()会报错详见下文错误行为小节可用allowEmpty选项抑制。负向 glob 作用于全部正向 glob。当使用 glob 数组时任何以!开头的负向 glob 都会从任何正向 glob 的匹配结果中移除文件——这是 gulp v5 引入的新语义v5 之前的行为有所不同详见下文负向 glob小节。gulp 中所有接受路径的地方几乎都支持 glob包括src()、watch()见 Watching Files以及ignore选项等因此掌握 glob 语法是高效使用 gulp 的前提。段与分隔符跨平台的一致性约定理解 glob 的第一步是掌握**段segment与分隔符separator**的概念段两个分隔符之间的内容。例如scripts/nested/index.js由scripts、nested、index.js三段组成。分隔符在 glob 中永远是/字符与操作系统无关——即使在路径分隔符为\的 Windows 上也不例外。在 glob 中\被保留用作转义字符escape character而不是路径分隔符。下面的示例中*被转义因此被当作字面量字符而非通配符glob_with_uncommon_\\*_character.js注这是 JavaScript 源码中的写法\\表示一个真正的反斜杠最终传给src()的 glob 字符串为glob_with_uncommon_\*_character.js其中\*意味着匹配字面量*字符。因此避免使用 Node 的path方法来创建 glob例如path.join。在 Windows 上Node 会使用\作为路径分隔符这样生成的glob是无效的const invalidGlob path.join(__dirname, src/*.js); // ❌ 在 Windows 上会产生无效 glob同理也要避免使用__dirname全局变量、__filename全局变量或process.cwd()来拼接 glob原因相同。这正是src()提供cwd、base等选项的原因——详见 src() API 参考 中的说明用选项来指定工作目录而不是用字符串拼接。特殊字符*单星匹配单个段内的任意字符*匹配单个段内任意数量的字符——包括零个字符。它适合匹配同一个目录内的文件。*.js这个 glob 会匹配index.js这类文件但不会匹配scripts/index.js跨了段scripts/nested/index.js跨了多段因为它只在单一段内生效。这是 glob 与正则表达式的一个重要区别*在 glob 中永远不会跨越/分隔符。特殊字符**双星跨段匹配**匹配跨多个段的任意数量字符——同样包括零个。它适合匹配嵌套目录中的文件。scripts/**/*.js这个 glob 会匹配scripts/index.jsscripts/nested/index.jsscripts/nested/twice/index.js务必注意限制双星 glob 的范围。在上面的示例中scripts/前缀是刻意保留的如果不加这个前缀**/*.js会匹配当前工作目录树下所有.js文件包括node_modules等大型目录中的文件导致匹配范围失控、性能下降。仓库测试 test/src.js 直接验证了双星 glob 的行为// 深层次 glob匹配嵌套目录下的 .jade 文件 var stream gulp.src(./fixtures/**/*.jade, { cwd: __dirname }); // 期望匹配 ./fixtures/test/run.jade // 更深的 glob./fixtures/**/*.dmc 期望匹配 2 个文件 var stream gulp.src(./fixtures/**/*.dmc, { cwd: __dirname }); // end 事件时断言 a 2测试中的cwd选项指向__dirname正是为了在不依赖 glob 字符串拼接的前提下指定基准目录。特殊字符!负向从结果中排除文件以!字符开头的 glob 会否定该 glob将其匹配的文件完全排除。负向 glob 是所有 glob 语法中最实用的部分常用于匹配全部但排除某些目录的场景。[scripts/**/*.js, !scripts/vendor/**]上面的数组会遍历scripts/目录下所有以.js结尾的文件但排除scripts/vendor/目录下的所有文件。v5 行为变化在 gulp v5 之前负向 glob 只对其在数组中的位置之后的 glob 生效而在 v5 中所有负向 glob 都会应用于每一个正向 glob。这意味着无论负向 glob 在数组中的位置如何它都会生效行为更符合直觉也与生态中大多数 globbing 库保持一致。负向 glob 也可以作为限制双星 glob的替代方案——与其在正向 glob 中层层限定前缀不如先全选、再排除[**/*.js, !node_modules/**]这个模式等效于匹配所有 JS 文件但排除node_modules目录在大型项目中比硬编码前缀更稳健。仓库测试 test/src.js 同样覆盖了负向 glob 场景var globArray [ ./fixtures/stuff/*.dmc, !fixtures/stuff/test.dmc, ]; // 最终只匹配到 ./fixtures/stuff/run.dmc 一个文件错误行为与allowEmpty当globs只能匹配单个文件如foo/bar.js这种不含通配符的路径且未找到匹配时src()会抛出 File not found with singular glob 错误要抑制该错误可将allowEmpty选项设为true。当传入无效的 glob 时会抛出 Invalid glob argument 错误。详见 src() API 参考。有序 globv5 的移除与替代方案v5 之前的 gulp 版本允许有序 globordered globs——即多个 glob 按给定顺序匹配文件控制输出顺序。这一特性已在 v5 中移除以对齐生态中大多数 globbing 库的语义。如果你确实需要有序 glob的功能例如按特定顺序合并第三方库文件可以使用ordered-read-streams库来合并多个流const order require(ordered-read-streams); exports.default function () { return order([ gulp.src(input/jquery/dist/jquery.js), gulp.src(input/detect_swipe/jquery.detect_swipe.js), ]).pipe(gulp.dest(output/)); }这个方案将每个src()产生的流按顺序组合再统一输出到目标目录保留了输出顺序的可控性。重叠 glob 与去重行为两个或多个 glob 如果有意或无意匹配到同一个文件即构成重叠overlapping。例如[**/*.js, src/*.js]中src/index.js会被两个 glob 同时匹配。重叠时的行为规则在同一个src()调用内gulp 会尽力去除重复文件默认按path属性去重可通过uniqueBy选项自定义去重键详见 src() API 参考。跨多个src()调用gulp 不会跨调用去重。如果两个不同的src()匹配到同一文件该文件会以两个 Vinyl 对象的形式进入管道。了解这一点有助于避免意外的重复输出——例如在管道中间再次调用src()追加文件时如果 glob 重叠文件会被再次加入详见 Working with Files 中的Adding files to the stream。源码视角globs 如何驱动 gulp 的核心 API从源码结构看gulp 本体index.js非常薄它把文件系统的读写能力委托给了vinyl-fs模块// index.js Gulp.prototype.src vfs.src; Gulp.prototype.dest vfs.dest; Gulp.prototype.symlink vfs.symlink;也就是说你调用的gulp.src(globs, [options])实际是 vinyl-fs 提供的适配器它负责把 glob 交给底层匹配库去定位文件、按匹配结果创建 Vinyl 文件对象path、contents、base等属性、并以 Node 流的形式输出。globs 是这一切的输入契约。在 package.json 中可以确认当前仓库对应 gulp 5.0.1 版本其核心依赖包括vinyl-fs、glob-watcher、undertaker、gulp-cli等——每个模块各司其职可参考 API Concepts 中的模块列表。glob 不仅驱动src()也驱动watch()watch(globs, [options], [task])使用文件系统监听器监听匹配 globs 的文件变化并触发任务执行详见 watch() API 参考 与 Watching Files。因此一套 glob 语法知识同时覆盖了读文件和盯文件两大场景。另外src()中与 glob 强相关的选项也值得掌握完整列表见 src() API 参考选项默认值与 glob 的关系cwdprocess.cwd()与相对路径拼接形成绝对路径用于避免用path.join()拼 globbase由 glob 推断显式设置 Vinyl 对象的base属性即 glob base见 API ConceptsallowEmptyfalse为true时抑制单个文件 glob 找不到匹配时的报错uniqueBypath按指定属性或函数结果去除流中的重复文件dotfalse为true时 glob 可匹配.gitignore这类点文件noglobstarfalse为true时把**当作*处理nocasefalse为true时执行大小写不敏感匹配matchBasefalse为true时不含/的 glob如*.js等效于**/*.jsignore—附加的排除 glob与负向 glob 合并生效这些选项大多直接透传给底层的 globbing 库如 glob-stream、anymatch理解它们能帮你写出更精确、更高效的匹配规则。进阶学习资源本文覆盖了 gulp 使用中绝大多数 glob 场景。若需要更深入的钻研社区中以下资料值得参考均可通过 npm/GitHub 搜索找到micromatch文档gulp 底层依赖的高性能 glob 匹配库涵盖完整的语法细节与选项。node-glob 的 Glob Primer最经典的 glob 语法入门读物详细解释了*、**、?、字符类等所有通配符语义。Begin 的 Globbing 文档从什么是 globbing讲起的简明教程。Wikipedia 的 Glob 词条了解 glob 的历史渊源与各语言实现差异。回到仓库本身Explaining Globs 是官方 Getting Started 系列见 getting-started/README的第 6 篇建议按顺序与 Working with Files 搭配阅读前者讲透匹配语法后者讲透文件在管道中的流转方式再结合 test/src.js 中的测试用例动手验证即可彻底掌握 gulp 的文件匹配体系。【免费下载链接】gulpA toolkit to automate enhance your workflow项目地址: https://gitcode.com/gh_mirrors/gu/gulp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表