gulp 学习笔记

在 gulp 的任务中,gulp.src 接口将匹配到的文件转化为可读的文件流,通过 .pipe 流经各插件进行处理,最终推送给 gulp.dest 所生成的可写文件流,生成文件写入磁盘。其中涉及到下面几个重要的库:

Vinyl

Vinyl 是一个文件描述器,通过它可以在内存中构建临时文件对象。

1
2
3
const Vinyl = require('vinyl')
const empty = new Vinyl()
console.dir(empty)

最终打印出来:

1
2
3
4
5
6
7
File {
stat: null,
_contents: null,
history: [],
_cwd: '/job/gulp-tutorial',
_isVinyl: true,
_symlink: null }

是一个空的文件对象。我们还可以为文件指定各种属性,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
const txt = new Vinyl({
cwd: '/',
base: '/test/',
path: '/test/file.txt',
contents: new Buffer('abc')
})

console.dir(txt)
console.log(txt.contents.toString())
console.log('path is: ' + txt.path)
console.log('basename is: ' + txt.basename)
console.log('filename without suffix: ' + txt.stem)
console.log('file extname is: ' + txt.extname)

打印出来是:

1
2
3
4
5
6
7
8
9
10
11
12
13
File {
stat: null,
_contents: Buffer [Uint8Array] [ 97, 98, 99 ],
history: [ '/test/file.txt' ],
_cwd: '/',
_base: '/test',
_isVinyl: true,
_symlink: null }
abc
path is: /test/file.txt
basename is: file.txt
filename without suffix: file
file extname is: .txt

vinyl 对像方法有:

  • file.isBuffer():判断文件内容是否是 Buffer 格式的
  • file.isStream():判断文件内容是否是 stream 形式的
  • file.isNull():判断文件内容是否为空

vinyl 对象的属性有:

  • file.cwd:当前工作目录,最后的斜杠会被删除,通过file.cwd = newCwd 可以设置新的值
  • file.base:文件基础目录,值等于 path.dirname(file.path)
  • file.path:文件的绝对路径
  • file.relative:文件的相对路径,值等于 path.resolve(file.base,file.path)

Vinyl-fs

Vinyl 虽然可以用于创建一个文件,也提供了 API 来设置或获取文件的内容,但只存在内存中,还不能文件系统进行接入。Vinyl-fs 可以读取磁盘中的文件,以 Vinyl 对象的格式保存在内存中,然后再将这个内存中的 Vinyl 对象写入文件系统。

1
2
3
4
const fs = require('vinyl-fs')

fs.src(['./src/*.js'])
.pipe(fs.dest('./output'))

这里匹配正则采用 GLOB 模式,也就是 shell 所使用的简化过的正则表达式:

  • 星号*匹配零个或多个任意字符
  • [abc]匹配任何一个列在方括号中的字符(要么匹配一个 a,要么匹配一个 b,要么匹配一个 c)
  • 问号?只匹配一个任意字符
  • 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如[0-9]表示匹配所有 0 到 9 的数字)

through2

vinyl-fs 使用了 through2 来处理文件流,through2 能把让开发者只关注对流的处理,而不需要每次都要去创建 Stream 然后进行 transform,through2 有两种用法:

1
2
through2(function(chunk,enc,cb){})
through2.obj(function(chunk,enc,cb){})

第一种用于处理普通 stream,第二个用于处理 object stream,例如我们可以写一个简单的 gulp 插件:

1
2
3
4
5
6
7
8
gulp.task('test',function(){
return gulp.src('./test.txt')
.pipe(through2.obj(function(chunk,enc,cb){
console.log('through2 in gulp')
cb(null,chunk)
}))
.pipe(gulp.dest('./'))
})

虽然这个插件啥都没做,但是的确打印出结果了,表明文件流经过了这个函数,因此我们可以对其进行二次加工,例如:

1
2
3
4
5
6
7
8
9
10
11
const fs = require('vinyl-fs')
const through2 = require('through2')

fs.src(['./src/*.js'])
.pipe(through2.obj(function (file, enc, cb) {
const content = 'hello'
file.contents = Buffer.from(content)
this.push(file)
cb()
}))
.pipe(fs.dest('./output'))

这里就把文件流传过来内容全都换成了 hello。