gulp简介及基本用法

基本操作

  1. 全局安装:npm install --global gulp
  2. 作为项目的开发依赖(devDependencies)安装:npm install --save-dev gulp
  3. 在项目根目录下创建一个名为 gulpfile.js 的文件:

    1
    2
    3
    4
    var gulp = require('gulp');
    gulp.task('default', function() {
    // 将你的默认的任务代码放在这
    });
  4. 运行 gulp:gulp,只书写gulp的话只会执行default的任务,要执行其他任务,可以输入gulp <task> <othertask>

官方文档

http://www.gulpjs.com.cn/docs/api/

API简单介绍

gulp的方法只有5个:
gulp.src() // 设置处理文件的路径
gulp.dest() // 设置处理后的文件存放路径
gulp.task() // 任务定义
gulp.pipe() // 处理管道运行
gulp.watch() // 文件监听

1. gulp.src(globs[,options])

输出符合所提供的匹配模式(glob)或者匹配模式的数组(array of globs)的文件。目前常用为直接写文件路径。

gulp.task('image', function() {
    gulp.src('src/img/**/*.*')          // src/img目录下的所有文件
        .pipe(gulp.dest('dist/img'));   // 存放到dist/img目录下
});

2. gulp.dest(path[, options])

将src匹配并处理后pipe过来的文件写到指定文件,也可以将它 pipe 到多个文件夹。如果某文件夹不存在,将会自动创建它。path为文件存放路径。也可以传入一个函数,在函数中返回相应路径。

gulp.task('image', function() {
    gulp.src('src/img/**/*.*')          // src/img目录下的所有文件
        .pipe(gulp.dest('dist/img'))    // 存放到dist/img目录下
        .pipe(gulp.dest('test/'));      // 再存放一份到test/目录
});

3. gulp.task(name[, deps], fn)

gulp.task('somename', function() {
  // 做一些事
});

定义一个执行任务。
name:任务的名字,如果你需要在命令行中运行你的某些任务,那么,请不要在名字中使用空格。
deps:类型:Array,非必须,一个包含任务列表的数组,这些任务会在你当前任务运行之前完成。依赖的异步任务必须要有异步执行方式:使用一个 callback,或者返回一个 promise 或 stream来通知主任务,前面的依赖任务已完成
gulp的task任务是按最大并发执行的,也就是全部同时执行。

gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {
  // 做一些事
});
// 常见的异步方式为返回一个stream,如下return
gulp.task('array', function() {
    return gulp.src('*.*')
        .pipe(gulp.dest('test/'));
})

fn: 该函数定义任务所要执行的一些操作。通常来说,它会是这种形式:gulp.src().pipe(someplugin())。

4. gulp.src().pipe()

任务的数据传递方法,将上一个插件处理后的文件数据传往下一个处理插件。

5. gulp.watch(glob[, opts], tasks)

监视文件,并且可以在文件发生改动时候做一些事情。
glob:一个 glob 字符串,或者一个包含多个 glob 字符串的数组,用来指定具体监控哪些文件的变动,常使用文件路径。
opts:传给 gaze 的参数。不常用。
tasks:类型:Array,需要在文件变动后执行的一个或者多个通过 gulp.task() 创建的 task 的名字。

gulp.watch('js/**/*.js', ['uglify','reload']); 
// 当指定文件变动时,就会执行uglify和reload任务

也可以 gulp.watch(glob[, opts], fn); fn为文件改变后执行的自定义回调。

6. gulp有无return的区别

依据gulp官方文档,gulp的task方法是按最大并发执行的,也就是说所有的task都会同时执行,而对于依赖于其他任务的异步task来说,就需要一个通知来告知该什么时候执行。故需要一个return。

gulp.task('js', ['css'], function() {
  // 做一些事
});
// js这个异步任务就需要css任务执行完毕后给一个提示,可以为如下3种方式
// 1.返回一个stream,就是直接return的方式
gulp.task('css', function() {
  var stream = gulp.src('client/**/*.css')
    .pipe(gulp.dest('build'));
  return stream;
});
// 2. 返回一个promise
gulp.task('css', function() {
  var deferred = Q.defer();
  // 执行异步的操作
  setTimeout(function() {
    deferred.resolve();
  }, 1);
  return deferred.promise;
});
// 3. 执行一个回调
gulp.task('css', function(cb) {
  exec('jekyll build', function(err) {
    if (err) return cb(err); // 返回 error
    cb(); // 完成 task
  });
});

基本的gulpfile.js示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//引入gulp及其插件模块
var gulp = require('gulp'); //gulp基本包
var autoprefixer = require('gulp-autoprefixer'); //css前缀处理
var cssnano = require('gulp-cssnano'); //css压缩
var uglify = require('gulp-uglify'); //压缩 JavaScript
var htmlmin = require('gulp-htmlmin'); //html压缩
var imagemin = require('gulp-imagemin'); //图片压缩
//注册样式编译任务
gulp.task('style', function() {
return gulp.src('src/css/*.css')
.pipe(autoprefixer({browsers: [
"ie >= 8",
"ie_mob >= 10",
"ff >= 26",
"chrome >= 30",
"safari >= 6",
"opera >= 23",
"ios >= 5",
"android >= 2.3",
"bb >= 10"
]}))
.pipe(cssnano())
.pipe(gulp.dest('dist/css'));
});
gulp.task('image', function() {
return gulp.src('src/img/**/*.*')
.pipe(imagemin())
.pipe(gulp.dest('dist/img'));
});
gulp.task('script', function() {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
gulp.task('html', function() {
return gulp.src('src/*.html')
.pipe(htmlmin({
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
}))
.pipe(gulp.dest('dist'));
});
//监听文档
gulp.task('serve', ['style', 'image', 'script', 'html'], function() {
gulp.watch('src/styles/*.css', ['style']);
gulp.watch('src/images/*.*', ['image']);
gulp.watch('src/scripts/*.js', ['script']);
gulp.watch('src/*.html', ['html']);
});

gulp@4版本

npm install --global gulp-cli
npm install --save-dev gulp
// 创建gulpfile.js

gulp任务:不再支持同步,任务是一个异步函数,可以返回stream、promise、event emitter、child process 或 observable。任务新增public和private类型。

组合任务:以前版本是通过第二个传参为任务名数组将任务进行组合,新版本使用series()parallel()进行组合,series()用于顺序执行,parallel()用于并发执行。以上两个函数都返回一个新的任务,也就是可以随意嵌套。

任务返回值:stream、promise、event emitter、child process 或 observable。如果任务(task)不返回任何内容,则必须使用 callback 来指示任务已完成。function callbackTask(cb){cb()}

src()

创建一个流,用于从文件系统读取 Vinyl 对象。src(globs, [options])

const { src, dest } = require('gulp');
function copy() {
  return src('input/*.js')
    .pipe(dest('output/'));
}

dest()

创建一个用于将 Vinyl 对象写入到文件系统的流。dest(directory, [options])

series()

将任务函数和/或组合操作组合成更大的操作,这些操作将按顺序依次执行。

parallel()

将任务功能和/或组合操作组合成同时执行的较大操作。

task()

已不在推荐使用,用函数名/series/parallel即可实现任务,gulp默认会执行exports.default的任务函数。

watch()

监听 globs 并在发生更改时运行任务。任务与任务系统的其余部分被统一处理。watch(globs, [options], [task])

const { watch } = require('gulp');
watch(['input/*.js', '!input/something.js'], function(cb) {
  // body omitted
  cb();
});

lastRun()

检索在当前运行进程中成功完成任务的最后一次时间。lastRun(task, [precision])。返回一个时间戳(以毫秒为单位),表示任务的最后完成时间。如果任务尚未运行或已经失败,则返回 undefined。

将上诉改写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//引入gulp及其插件模块
var {src, dest, watch, series, parallel} = require('gulp'); //gulp基本包
var autoprefixer = require('gulp-autoprefixer'); //css前缀处理
var cssnano = require('gulp-cssnano'); //css压缩
var uglify = require('gulp-uglify'); //压缩 JavaScript
var htmlmin = require('gulp-htmlmin'); //html压缩
var imagemin = require('gulp-imagemin'); //图片压缩

function style() {
return gulp.src('src/css/*.css')
.pipe(autoprefixer({browsers: [
"ie >= 8",
"ie_mob >= 10",
"ff >= 26",
"chrome >= 30",
"safari >= 6",
"opera >= 23",
"ios >= 5",
"android >= 2.3",
"bb >= 10"
]}))
.pipe(cssnano())
.pipe(gulp.dest('dist/css'));
}

function image() {
return gulp.src('src/img/**/*.*')
.pipe(imagemin())
.pipe(gulp.dest('dist/img'));
}

function script() {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
}

function html() {
return gulp.src('src/*.html')
.pipe(htmlmin({
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
}))
.pipe(gulp.dest('dist'));
}

function serve() {
watch('src/styles/*.css', style)
watch('src/images/*.*', image)
watch('src/scripts/*.js', script)
watch('src/*.html', html)
}

exports.default = series(style, image, script, html, serve)

gulp插件编写

gulp插件,对stream流操作的一个中间函数,并返回一个数据流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var gutil = require('gulp-util') // gulp工具类
var through = require('through2') // stream处理
var pp = require('preprocess') // 文件流转换
var PLUGIN_NAME = 'PUBSRC' // 插件名称

module.exports = function(pubsrc) {
pubsrc = pubsrc || ''
return through.obj(function(file, enc, cb) {
if (file.isNull()) { // 空内容,直接跳过
this.push(file)
return cb()
}

if (file.isStream()) {
this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'))
return cb()
}

var content = pp.preprocess(file.contents.toString(), {})
content = content.replace(/PUBSRC/ig, pubsrc)

file.contents = new Buffer(content) // 文件流替换赋值

this.push(file) // 文件流返回
cb()
})
}

THE END!