var glob = require("glob")
// options is optional
glob("**/*.js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
})
gulp 拾遗 (2) - 认识 glob
为什么要用 glob
gulp 的 task 函数一般起自于 src :
简单来说, src API 根据输入参数(input/*.js),从文件系统中读取文件流(stream),从而进行后续的操作。src 函数的第一个输入参数称为 pattern,是一个 glob 语句。glob 语句类似于 unix shell 中描述文件的方式。
glob 语句很容易理解,比如上面的 input/*.js,表示 input 目录下(不包含子目录),扩展名为 js 的所有文件。
如果想要自如的编写 gulp 脚本,掌握 glob 语句是必不可少的。事实上不只 gulp,其他构建工具如 webpack,也使用 glob 语句来匹配文件。我想原因无非有两个,一是因为 glob 语法非常简单,容易学习。另一方面, glob 借鉴了 unix/linux 中文件匹配的语法,而很多工程师都有 unix/linux 经验,学习成本很低。就像当年 android 使用 java 作为开发语言以至于收到很多 java 程序员的喜爱和支持。
node-glob
目前,glob 最好的实现应该是 node-glob。下面是一个简单的例子,用于查找所有目录下的 js 文件。第一个参数称为 pattern,描述待匹配文件的路径特征;第二个参数是 options,提供一些增强的配置项,如配置工作目录,模式,排序规则,等等。第三个参数是回调函数。可以看到 glob 是异步函数。
pattern
pattern 的类型是字符串或者字符串数组,每个字符串都可以包含以下几种关键字。
上面的规则不算太复杂(相比正则表达式),但仍需要搭配一些练习才能掌握。
options
options 中的选项很多,拣几个常用的讲一下。
cwd
cwd 表示当前工作目录(current work directory)。也就是 process.cwd(),也即使 nodejs 脚本的执行目录。什么意思呢?比如,有个文件 index.js,我们在 /home/wangpin 下执行:
此时,cwd 是 /home/wangpin。 如果我们在 home 目录下启动 index.js:
此时,cwd 是 /home。
简单的说, cwd 是我们运行脚本的目录,不是脚本的存放目录 。
ignore
设置一个 pattern 用于忽略某些文件。虽然有 ! 和 ^ 可以用来做 exclude,但总体来说, pattern 是用来做 include,在其中夹杂复杂的 exclude 规则会让整个 pattern 变得非常难以理解。更简单的办法是利用 ignore option 来设置过滤规则。即
比如,选取 input 目录下的 js 文件,同时过滤掉 min.js 文件:
gulp 中的 glob
gulp 并没有直接使用 node-glob,它自己做了很多的封装,创造出了 glob-stream,vinyl-fs 等一系列满足自身需求,同时也很有现实意义的库。gulp 的官方文档中队 vinyl 和 glob 也做了详细的阐释,请移步 concepts。
其他脚本中的 glob
编写任何涉及到文件检索的脚本,glob 都应该是首选。比如,我们想要将 dist 目录中的所有文件上传到 aws s3。如果用 fs api 生写,仅仅是遍历所有文件,就需要下面这一大段代码:
这还没有涉及复杂的 include 和 exclude 规则,已经是比较大的函数了。 如果用 glob 重构一下呢?
代码量减少的同时,复杂的include/exclude部分由专业的 glob 来负责。
总结
glob 是简单而强大的文件匹配库,gulp,webpack 等构架工具都使用它来简单化文件匹配工作,某种意义上来说它已经是文件匹配的事实标准。glob 也可以用于其他涉及文件匹配的应用场景,不必拘泥于已有的场合。
文中提到的库,文档,及相关资料地址。