# gulp

Table of Contents generated with DocToc (opens new window)

# gulp简介

官网介绍gulp是一个流构建系统(The streaming build system)

gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用它,我们不仅可以很愉快的编写代码,而且大大提高我们的工作效率。

gulp是基于Nodejs的自动任务运行器, 她能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤。在实现上,她借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级的输入,使得在操作上非常简单。

gulp 和 grunt 非常类似,但相比于 grunt 的频繁 IO 操作,gulp 的流操作,能更快地更便捷地完成构建工作。

gulp常用地址:

gulp官方网址:http://gulpjs.com

gulp插件地址:http://gulpjs.com/plugins

gulp 官方API:https://github.com/gulpjs/gulp/tree/master/docs/api

gulp 中文API:http://www.ydcss.com/archives/424

# 安装

步骤一:以全局方式安装gulp,执行gulp任务

npm install -g gulp
1

步骤二:把gulp安装在本地,调用插件的功能

npm install --save-dev gulp
1

# 作用

  • Sass/less编译
  • Css Js 图片压缩
  • Css Js 合并
  • Css Js 内联
  • Html的include功能
  • Autoprefixer
  • 自动刷新
  • 去缓存
  • Handlebars模板文件的预编译
  • 雪碧图
  • ESLint rem移动端适配方案

gulp有很多插件可以做到你想做的事情,插件地址 (opens new window)

# 应用

安装了gulp以后你需要在你的文件夹里边创建一个gulpfile.js文件,它是gulp的配置文件。在这里边你可以创建你要创建的任务,以及应用各种插件,相当于webpack的webpack.config.js

大概就是这样的一份文件

//导入工具包 require('node_modules里对应模块')
var gulp = require('gulp'), //本地安装gulp所用到的地方
    concat = require('gulp-concat'),//合并文件 --合并只是放一起--压缩才会真正合并相同样式
    less = require('gulp-less'),//编译less文件
    cssmin = require('gulp-minify-css'),//压缩css文件
    rename = require('gulp-rename'),//设置压缩后的文件名
    autoprefixer = require('gulp-autoprefixer'),//给 CSS 增加前缀。解决某些CSS属性不是标准属性,有各种浏览器前缀的情况
    imagemin = require('gulp-imagemin'),  //图片压缩
    spriter=require('gulp-css-spriter');//合并图片

//编译less文件   定义一个testLess任务(自定义任务名称)
gulp.task('testLess', function () {
    gulp.src('src/less/index.less') //该任务针对的文件
        .pipe(less()) //该任务调用的模块
        .pipe(gulp.dest('src/css')); //将会在src/css下生成index.css
});

//压缩css文件
gulp.task('minifycss', function() {
    gulp.src('src/css/index.css')      //压缩的文件
        .pipe(cssmin())   //执行压缩
        .pipe(gulp.dest('src/cssmin'))   //输出文件夹
});

gulp.task('default',['testLess','minifycss'],function(){//定义默认任务  先执行testLess和minifycss 再执行console.log('hello world');
    console.log('hello world');
}); 

//gulp.task(name[, deps], fn) 定义任务  name:任务名称 deps:依赖任务名称 fn:回调函数
//gulp.src(globs[, options]) 执行任务处理的文件  globs:处理的文件路径(字符串或者字符串数组) 
//gulp.dest(path[, options]) 处理完后文件生成路径
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

# API (opens new window)

# src

src用于创建一个流用于读取文件系统里的文件对象

语法

src(globs, [options])
1

globs:是用来监控或者找到文件 options:是你要对你监控文件做的一些事情具

# dest

dest 用于创建一个将文件对象写入文件系统的流,他是一个可以在管道的中间或末尾使用的流

语法

dest(directory, [options])
1

directory:将写入文件的输出目录的路径。如果使用函数,将使用每个Vinyl对象调用该函数,并且必须返回字符串目录路径。

options:是你要对你写入文件要做的事情

symlink 创建用于将Vinyl对象链接到文件系统的流。就是一个符号链接,即其实就是linux里的软连接,就是副本,但是当删除源文件时,软连接文件也会被删除。

语法

symlink(directory, [options])
1

directory:输出目录的路径,其中将创建符号链接。如果使用函数,将使用每个Vinyl对象调用该函数,并且必须返回字符串目录路径。 options:是你要对你输出目录设置的选项。

# lastRun

检索在当前运行过程中上次成功完成任务的时间。在观察程序运行时,对后续任务运行最有用。

与之结合使用时src(),通过跳过自上次成功完成任务以来未发生更改的文件,启用增量构建以加快执行时间。

用法:

const { src, dest, lastRun, watch } = require('gulp');
const imagemin = require('gulp-imagemin');

function images() {
  return src('src/images/**/*.jpg', { since: lastRun(images) })
    .pipe(imagemin())
    .pipe(dest('build/img/'));
}

function watch() {
  watch('src/images/**/*.jpg', images);
}

exports.watch = watch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

语法

lastRun(task, [precision])
1

task:任务函数或已注册任务的字符串别名。

precision:时间戳精度,默认值:1000

# series

将任务函数和/或组合操作组合成更大的操作,这些操作将按顺序依次执行。使用series()和组合操作的嵌套深度没有强制限制parallel()。

语法

series(...tasks)
1

...task:任意数量的任务函数都可以作为单独的参数传递。如果您之前已注册任务,则可以使用字符串,但不建议这样做。

用法:

const { series } = require('gulp');

function javascript(cb) {
  // body omitted
  cb();//相当于回调:官网是这么介绍的应该由一些异步工作调用
}

function css(cb) {
  // body omitted
  cb();
}

exports.build = series(javascript, css);
1
2
3
4
5
6
7
8
9
10
11
12
13

# parallel

将任务函数和/或组合操作组合成将同时执行的更大操作。使用series()和组合操作的嵌套深度没有强制限制parallel()

语法

parallel(...tasks)
1

...task:任意数量的任务函数都可以作为单独的参数传递。如果您之前已注册任务,则可以使用字符串,但不建议这样做。

# watch

允许在发生更改时观看全局并运行任务。任务与任务系统的其余部分统一处理。

语法:

watch(globs, [options], [task])
1

参数

globs:需要被监控的文件

options:控制监控的选项 task:需要被监控的任务

用法

const { watch } = require('gulp');

const watcher = watch(['input/*.js']);

watcher.on('change', function(path, stats) {
  console.log(`File ${path} was changed`);
});

watcher.on('add', function(path, stats) {
  console.log(`File ${path} was added`);
});

watcher.on('unlink', function(path, stats) {
  console.log(`File ${path} was removed`);
});

watcher.close();//关闭监控
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# task

定义任务系统中的任务。任务然后可以通过命令行和访问series(),parallel()以及lastRun()API的。

语法

task([taskName], taskFunction)
1

参数

taskName:任务名称

taskFunction: 一个任务功能或组成的工作-通过产生series()和parallel()。理想情况下是命名函数。可以附加任务元数据以向命令行提供额外信息。

用法:

将命名函数注册为任务:

const { task } = require('gulp');

function build(cb) {
  // body omitted
  cb();
}

task(build);
1
2
3
4
5
6
7
8

将匿名函数注册为任务:

const { task } = require('gulp');

task('build', function(cb) {
  // body omitted
  cb();
});
1
2
3
4
5
6

检索先前已注册的任务:

const { task } = require('gulp');

task('build', function(cb) {
  // body omitted
  cb();
});

const build = task('build');`
1
2
3
4
5
6
7
8

# registry

允许将自定义注册表插入任务系统,该任务系统可以提供共享任务或增强功能。

未测试(后续更新)

# tree

获取当前任务依赖关系树 - 在极少数情况下需要它。

通常,tree()gulp使用者不会使用它,但它是暴露的,因此CLI可以显示gulpfile中定义的任务的依赖关系图

# Vinyl

虚拟文件格式。读取文件时src(),会生成Vinyl对象来表示文件 - 包括路径,内容和其他元数据。

Vinyl对象可以使用插件进行转换。它们也可以使用持久化到文件系统dest()。

创建自己的Vinyl对象时src()- 使用外部vinyl模块而不是生成- 如下面的用法所示。

用法

const Vinyl = require('vinyl');

const file = new Vinyl({
  cwd: '/',
  base: '/test/',
  path: '/test/file.js',
  contents: new Buffer('var x = 123')
});

file.relative === 'file.js';

file.dirname === '/test';
file.dirname = '/specs';
file.path === '/specs/file.js';

file.basename === 'file.js';
file.basename = 'file.txt';
file.path === '/specs/file.txt';

file.stem === 'file';
file.stem = 'foo';
file.path === '/specs/foo.txt';
file.extname === '.txt';
file.extname = '.js';
file.path === '/specs/file.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

# 一些常用的插件

官网的插件太多了,下面就是介绍一些常用的插件,官网插件地址 (opens new window)

# 匹配符 *、**、!、{}

gulp.src('./js/*.js')               // * 匹配js文件夹下所有.js格式的文件
gulp.src('./js/**/*.js')            // ** 匹配js文件夹的0个或多个子文件夹
gulp.src(['./js/*.js','!./js/index.js'])    // ! 匹配除了index.js之外的所有js文件
gulp.src('./js/**/{omui,common}.js')        // {} 匹配{}里的文件名
1
2
3
4

# 文件操作

# del (替代gulp-clean)

var del = require('del');

del('./dist');                      // 删除整个dist文件夹
1
2
3

# gulp-rename

描述:重命名文件。

var rename = require("gulp-rename");

gulp.src('./hello.txt')
  .pipe(rename('gb/goodbye.md'))    // 直接修改文件名和路径
  .pipe(gulp.dest('./dist')); 
 
gulp.src('./hello.txt')
  .pipe(rename({
    dirname: "text",                // 路径名
    basename: "goodbye",            // 主文件名
    prefix: "pre-",                 // 前缀
    suffix: "-min",                 // 后缀
    extname: ".html"                // 扩展名
  }))
  .pipe(gulp.dest('./dist'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# gulp-concat

描述:合并文件。

var concat = require('gulp-concat');

gulp.src('./js/*.js')
    .pipe(concat('all.js'))         // 合并all.js文件
    .pipe(gulp.dest('./dist'));
    
gulp.src(['./js/demo1.js','./js/demo2.js','./js/demo2.js'])
    .pipe(concat('all.js'))         // 按照[]里的顺序合并文件
    .pipe(gulp.dest('./dist'));
1
2
3
4
5
6
7
8
9

# gulp-filter

描述:在虚拟文件流中过滤文件。

var filter = require('gulp-filter');

const f = filter(['**', '!*/index.js']);
gulp.src('js/**/*.js')
    .pipe(f)                        // 过滤掉index.js这个文件
    .pipe(gulp.dest('dist'));

const f1 = filter(['**', '!*/index.js'], {restore: true});
gulp.src('js/**/*.js')
    .pipe(f1)                       // 过滤掉index.js这个文件
    .pipe(uglify())                 // 对其他文件进行压缩
    .pipe(f1.restore)               // 返回到未过滤执行的所有文件
    .pipe(gulp.dest('dist'));       // 再对所有文件操作,包括index.js
1
2
3
4
5
6
7
8
9
10
11
12
13

# 压缩

# gulp-uglify

描述:压缩js文件大小。

var uglify = require("gulp-uglify");

gulp.src('./hello.js')
    .pipe(uglify())                 // 直接压缩hello.js
    .pipe(gulp.dest('./dist'))
    
 gulp.src('./hello.js')
    .pipe(uglify({
        mangle: true,               // 是否修改变量名,默认为 true
        compress: true,             // 是否完全压缩,默认为 true
        preserveComments: 'all'     // 保留所有注释
    }))
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9
10
11
12
13

# gulp-csso | gulp-minify-css

描述:压缩优化css。

var csso = require('gulp-csso');

gulp.src('./css/*.css') .pipe(csso()) .pipe(gulp.dest('./dist/css'))

# gulp-html-minify

描述:压缩HTML。

var htmlminify = require('gulp-html-minify');

gulp.src('index.html')
    .pipe(htmlminify())
    .pipe(gulp.dest('./dist'))
1
2
3
4
5

# gulp-imagemin

描述:压缩图片。

var imagemin = require('gulp-imagemin');

gulp.src('./img/*.{jpg,png,gif,ico}')
    .pipe(imagemin())
    .pipe(gulp.dest('./dist/img'))
1
2
3
4
5

# gulp-zip

描述:ZIP压缩文件。

var zip = require('gulp-zip');

gulp.src('./src/*')
    .pipe(zip('all.zip'))                   // 压缩成all.zip文件
    .pipe(gulp.dest('./dist'))
1
2
3
4
5

# JS/CSS自动注入

# gulp-autoprefixer

描述:自动为css添加浏览器前缀。

var autoprefixer = require('gulp-autoprefixer');

gulp.src('./css/*.css')
    .pipe(autoprefixer())           // 直接添加前缀
    .pipe(gulp.dest('dist'))

gulp.src('./css/*.css')
    .pipe(autoprefixer({
        browsers: ['last 2 versions'],      // 浏览器版本
        cascade:true                       // 美化属性,默认true
        add: true                           // 是否添加前缀,默认true
        remove: true                        // 删除过时前缀,默认true
        flexbox: true                       // 为flexbox属性添加前缀,默认true
    }))
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

查看更多配置:options (opens new window)

更多浏览器版本:browsers (opens new window)

# gulp-useref

描述:解析构建块在HTML文件来代替引用未经优化的脚本和样式表。

// index.html

<!-- build:css /css/all.css -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<!-- endbuild -->

// gulpfile.js

var useref = require('gulp-useref');

gulp.src('index.html')
    .pipe(useref())
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14

替换之后的index.html中就会变成:

<link rel="stylesheet" href="css/all.css">  // 之前的两个<link>替换成一个了
1

# gulp-rev

描述:给静态资源文件名添加hash值:unicorn.css => unicorn-d41d8cd98f.css

var rev = require('gulp-rev');

gulp.src('./css/*.css')
    .pipe(rev())
    .pipe(gulp.dest('./dist/css'))
1
2
3
4
5

# gulp-rev-replace

描述:重写被gulp-rev重命名的文件名。

var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var useref = require('gulp-useref');

gulp.src('index.html')
    .pipe(useref())                         // 替换HTML中引用的css和js
    .pipe(rev())                            // 给css,js,html加上hash版本号
    .pipe(revReplace())                     // 把引用的css和js替换成有版本号的名字
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9

# gulp-html-replace

描述:替换html中的构建块。

// index.html

<!-- build:css -->                          // css是buildName,可以自己定义
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<!-- endbuild -->

// gulpfile.js

var htmlreplace = require('gulp-html-replace');

gulp.src('index.html')
    .pipe(htmlreplace({
        'css':'all.css'                     // css是index.html中定义的buildName
    }))
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

替换之后的index.html中就会变成:

<link rel="stylesheet" href="all.css">      // 之前的两个<link>替换成一个了
1

# 流控制

# gulp-if

描述:有条件地运行一个任务。

var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var condition = true; 

gulp.src('./js/*.js')
    .pipe(gulpif(condition, uglify(), concat('all.js')))  // condition为true时执行uglify(), else 执行concat('all.js')
    .pipe(gulp.dest('./dist/'));
1
2
3
4
5
6
7
8

# 工具

# gulp-load-plugins

描述:从包的依赖和附件里加载gulp插件到一个对象里给你选择。

// package.json 

"devDependencies": {
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.1",
    "gulp-rename": "^1.2.2",
    "gulp-uglify": "^2.0.1"
}

// gulpfile.js

var $ = require('gulp-load-plugins')();     // $ 是一个对象,加载了依赖里的插件

gulp.src('./**/*.js')
    .pipe($.concat('all.js'))               // 使用插件就可以用$.PluginsName()
    .pipe($.uglify())
    .pipe($.rename('all.min.js'))
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# gulp-sass

var sass = require('gulp-sass');

gulp.src('./sass/**/*.scss')
    .pipe(sass({
        outputStyle: 'compressed'           // 配置输出方式,默认为nested
    }))
    .pipe(gulp.dest('./dist/css'));
    
gulp.watch('./sass/**/*.scss', ['sass']);   // 实时监听sass文件变动,执行sass任务
1
2
3
4
5
6
7
8
9

# gulp-less

描述 :编译Less

var gulp = require('gulp'),
    less = require("gulp-less");
 
gulp.task('compile-less', function () {
    gulp.src('less/*.less')
    .pipe(less())
    .pipe(gulp.dest('dist/css'));
});
1
2
3
4
5
6
7
8

# gulp-babel

描述:将ES6代码编译成ES5。

var babel = require('gulp-babel');

gulp.src('./js/index.js')
    .pipe(babel({
        presets: ['es2015']
    }))
    .pipe(gulp.dest('./dist'))
1
2
3
4
5
6
7

# gulp-jshint JS代码检查

var gulp = require('gulp');
var jshint = require("gulp-jshint");
 
gulp.task('jsLint', function () {
    gulp.src('js/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter()); // 输出检查结果
});
1
2
3
4
5
6
7
8

# gulp-livereload 自动刷新

描述:当代码变化时,它可以帮助我们自动刷新页面,该插件最好配合谷歌浏览器,且要安装livereload chrome extension扩展插件,否则无效。

var gulp = require('gulp'),
    less = require('gulp-less'),
    livereload = require('gulp-livereload');
 
gulp.task('less', function() {
  gulp.src('less/*.less')
    .pipe(less())
    .pipe(gulp.dest('css'))
    .pipe(livereload());
});
 
gulp.task('watch', function() {
  livereload.listen(); //要在这里调用listen()方法
  gulp.watch('less/*.less', ['less']);  //监听目录下的文件,若文件发生变化,则调用less任务。
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# gulp-cached 缓存构建过的文件

描述:就是将构建过的文件,生成一个hash,缓存在内存中,直到这个文件被更新,则只更新这个文件,而不再会一次性重新构建全部监控文件。

对比gulp-watch:它不会管你当前更新的是哪个文件,总之,当你告诉他监控某个目录,那么当这个目录里有某个文件更新了,他就会一次性的把目录下的文件全部执行一次task

var cached = require('gulp-cached');
var print = require('gulp-print');

gulp.task('esx-component', function() {
	gulp.src(esxSrc)
	    .pipe(cached('esx-component'))
	    .pipe(print())
	    .pipe(babel({
		    presets: ['react', 'es2015'],
		    plugins: [
			    "transform-es2015-block-scoping",
			    "transform-class-properties",
			    "transform-es2015-computed-properties",
			    "transform-es2015-modules-amd"
		    ]
	    }))
	    .pipe(gulp.dest('./public/js/component'));
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Last Updated: 4/15/2020, 5:02:25 PM