gulp 笔记 要点概况

gulp 是基于 node 实现 Web 前端自动化开发的工具。

gulp 还可以做很多事,例如:

  • 压缩CSS
  • 压缩图片
  • 编译Sass/LESS
  • 编译CoffeeScript
  • markdown 转换为 html
一、安装gulp

1、安装gulp

$ npm install -g gulp                            //安装全局包
$ npm install -g gulp-cli                        //安装gulp-cli 

2、创建项目目录并进入

$ npx mkdirp my-project                           //使用mkdirp命令创建my-project目录
$ cd my-project                                   //进入目录
$ npm init  -y                                    //在项目目录下 创建 package.json 文件 

3、安装 gulp,作为开发时依赖项

$ npm install --save-dev gulp                    //安装到开发依赖
$ gulp -v                                        //查看版本信息

4、在项目根目录下创建一个名为 gulpfile.js 的文件:

var gulp = require('gulp');
gulp.task('default', function() {                 // 将你的默认的任务代码放在这
});
二、gulp基本转换流程

1、找到 js/目录下的所有 .js 文件
2、压缩这些 js 文件
3、将压缩后的代码另存在 dist/js/ 目录下

// 压缩 JavaScript 文件
var gulp = require('gulp')                       // 获取 gulp
var uglify = require('gulp-uglify')              // 获取 uglify 模块(用于压缩 JS)

gulp.task('script', function(done) {
        gulp.src('js/*.js')                      // 1. src找到文件
        //.pipe是接受上一个流的结果,并返回一个处理后流的结果
        .pipe(uglify())                          // uglify 模块压缩文件
        .pipe(gulp.dest('dist/js'));             // dest输出压缩文件
        done();                                  //要求必须有回调函数
});

代码执行后文件结构
└── js/
│   └── a.js
└── dist/
    └── js/
        └── a.js
  • src() 读取文件然后生成一个 Node 流(stream)。它将所有匹配的文件读取到内存中并通过流(stream)进行处理。
  • 流(stream)所提供的主要的 API 是 .pipe() 方法。
  • dest() 接受一个输出目录作为参数,它会将文件内容及文件属性写入到指定的目录中。

gulp 还提供了 symlink() 方法,类似 dest(),但是创建的是链接而不是文件。

三、特殊字符 * 、* *、!、{}
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、! 反取,glob 数组中的取反必须跟在一个非取反的后面。

四、任务(task)

每个 gulp 任务(task)都是一个异步的 JavaScript 函数。
此函数是一个可以接收 callback 作为参数的函数,或者是一个返回 stream、promise、event emitter、child process 或 observable 类型值的函数。

1、导出任务
被 gulpfile 导出(export)的任务为公开任务,未被导出的任务被认为是私有任务。

const { series } = require('gulp');
function clean(cb) {                             // clean函数未被export导出是私有任务
  // ...                                         // 它仍然可以被用在 series()组合中。
  cb();
}
function build(cb) {
  // ...                                         // 它仍然可以被用在 series()组合中。
  cb();                                
}
exports.build = build;     // build函数被export导出了是公开任务,可以被 gulp命令直接调用。
exports.default = series(clean, build);
  • 公开任务(Public tasks) 从 gulpfile 中被导出(export),可以通过 gulp 命令直接调用。
  • 私有任务(Private tasks) 被设计为在内部使用,通常作为 series() 或 parallel() 组合的组成部分。

2、组合任务
Gulp 提供了两个强大的组合方法: series() 和 parallel(),允许将多个独立的任务组合为一个更大的操作。

  • 这两个方法都可以接受任意数目的任务(task)函数或已经组合的操作。
  • series() 和 parallel() 可以互相嵌套至任意深度。
const { series } = require('gulp');
function transpile(cb) {
  // ...   
  cb();
}
function bundle(cb) {
  // ...   
  cb();
}
exports.build = series(transpile, bundle);         //按顺序执行
const { parallel } = require('gulp');
function javascript(cb) {
  // ...  
  cb();
}
function css(cb) {
  // ...  
  cb();
}
exports.build = parallel(javascript, css);          //以最大并发来运行
  • 如果需要让任务(task)按顺序执行,请使用 series() 方法。
  • 对于希望以最大并发来运行的任务(tasks),可以使用 parallel() 方法。
const { series, parallel } = require('gulp');
function clean(cb) {
  // ...  
  cb();
}
function css(cb) {
  // ...  
  cb();
}
function javascript(cb) {
  // ...  
  cb();
}
exports.build = series(clean, parallel(css, javascript)); //可以任意嵌套
五、异步执行

当从任务(task)中返回 stream、promise、event emitter、child process 或 observable 时,成功或错误值将通知 gulp 是否继续执行或结束。如果任务(task)出错,gulp 将立即结束执行并显示该错误。

1、返回 stream(流)

const { src, dest } = require('gulp');
function streamTask() {
  return src('*.js')
    .pipe(dest('output'));
}
exports.default = streamTask

2、返回 promise(应答)

function promiseTask() {
  return Promise.resolve('the value is ignored');
}
exports.default = promiseTask;

3、返回 event emitter(事件发射器)

const { EventEmitter } = require('events');
function eventEmitterTask() {
  const emitter = new EventEmitter();
  // 发射必须异步,否则gulp无法监听
  setTimeout(() => emitter.emit('finish'), 250);
  return emitter;
}
exports.default = eventEmitterTask;

4、返回 child process(子进程)

const { exec } = require('child_process');
function childProcessTask() {
  return exec('date');
}
exports.default = childProcessTask;

5、返回 RxJS observable(观察对象)

var Observable = require('rx').Observable;
gulp.task('sometask', function() {
    return Observable.return(42);
});

6、使用 callback
如果任务(task)不返回任何内容,则必须使用 callback 来指示任务已完成。示例中,callback 将作为cb() 的参数传递给你的任务(task)。

function callbackTask(cb) {
  //...
  cb();
}
exports.default = callbackTask;

如需通过 callback 把任务(task)中的错误告知 gulp,将 Error 作为 callback 的参数。

function callbackError(cb) {
//...
  cb(new Error('kaboom'));
}
exports.default = callbackError;

7、使用 async/await
如果不使用前面提供到几种方式,你还可以将任务(task)定义为一个 async 函数,它将利用 promise 对你的任务(task)进行包装。这将允许你使用 await 处理 promise,并使用其他同步代码。

const fs = require('fs');
async function asyncAwaitTask() {
  const { version } = fs.readFileSync('package.json');
  console.log(version);
  await Promise.resolve('some result');
}
exports.default = asyncAwaitTask;
六、处理文件

gulp 暴露了 src() 和 dest() 方法用于处理计算机上存放的文件。

  • 由 src() 产生的流(stream)应当从任务(task)中返回并发出异步完成的信号
const { src, dest } = require('gulp');
exports.default = function() {
  return src('src/*.js')
    .pipe(dest('output/'));
}
  • 流(stream)所提供的主要的 API 是 .pipe() 方法,用于连接转换流(Transform streams)或可写流(Writable streams)。
const { src, dest } = require('gulp');
const babel = require('gulp-babel');
exports.default = function() {
  return src('src/*.js')
    .pipe(babel())
    .pipe(dest('output/'));
}
  • dest() 接受一个输出目录作为参数,当它接收到通过管道(pipeline)传输的文件时,它会将文件内容及文件属性写入到指定的目录中。
  • gulp 还提供了 symlink() 方法,其操作方式类似 dest(),但是创建的是链接而不是文件
  • 利用 .pipe() 方法将插件放置在 src() 和 dest() 之间,并转换流(stream)中的文件。
  • src() 也可以放在管道(pipeline)的中间,以根据给定的 glob 向流(stream)中添加文件。
  • 新加入的文件只对后续的转换可用。如果与之前的有重复,仍然会再次添加文件。
const { src, dest } = require('gulp');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
exports.default = function() {
  return src('src/*.js')
    .pipe(babel())
    .pipe(src('vendor/*.js'))
    .pipe(uglify())
    .pipe(dest('output/'));
}
  • dest() 可以用在管道(pipeline)中间用于将文件的中间状态写入文件系统。
  • 此功能可用于在同一个管道(pipeline)中创建未压缩(unminified)和已压缩(minified)的文件。
const { src, dest } = require('gulp');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const rename = require('gulp-rename');
exports.default = function() {
  return src('src/*.js')
    .pipe(babel())
    .pipe(src('vendor/*.js'))
    .pipe(dest('output/'))
    .pipe(uglify())
    .pipe(rename({ extname: '.min.js' }))
    .pipe(dest('output/'));
}

流动(streaming)、缓冲(buffered)和空(empty)模式。这些模式可以通过对 src()bufferread 参数进行设置。、

  • 缓冲(Buffering)模式是默认模式,将文件内容加载内存中。插件通常运行在缓冲(buffering)模式下。
  • 流动(Streaming)模式主要用于操作无法放入内存中的大文件,例如巨幅图像或电影。文件内容从文件系统中以小块的方式流式传输,而不是一次性全部加载。
  • 空(Empty)模式不包含任何内容,仅在处理文件元数据时有用。
七、文件监控

gulp api 中的 watch() 方法利用文件系统的监控程序(file system watcher)将 globs 与 任务(task) 进行关联。它对匹配 glob 的文件进行监控,如果有文件被修改了就执行关联的任务(task)。

const { watch, series } = require('gulp');
function clean(cb) {
//...
  cb();
}
function javascript(cb) {
//...
  cb();
}
function css(cb) {
//...
  cb();
}
watch('src/*.css', css);                          // 可以只关联一个任务
watch('src/*.js', series(clean, javascript));     // 或者关联一个任务组合

1、可监控的事件

  • 只要创建、更改或删除文件,文件监控程序就会执行关联的任务(task)
  • 可以在调用 watch() 方法时通过 events 参数进行指定。
  • 可用的有 'add'、'addDir'、'change'、'unlink'、'unlinkDir'、'ready'、'error'。
  • 还有一个 'all' 事件,它表示除 'ready' 和 'error' 之外的所有事件。
const { watch } = require('gulp');
// 所有事件都将被监控
watch('src/*.js', { events: 'all' }, function(cb) {  
 //...
  cb();
});

2、初次执行
调用 watch() 之后,任务只有在修改后还会执行。如需在文件修改之前执行,也就是调用 watch() 之后立即执行,请将 ignoreInitial 参数设置为 false

const { watch } = require('gulp');
// 关联的任务(task)将在启动时执行
watch('src/*.js', { ignoreInitial: false }, function(cb) {
//...
  cb();
});

3、队列
每一次文件修改只产生一次关联任务的执行并放入队列中。如需禁止队列,请将 queue 参数设置为 false。

const { watch } = require('gulp');
//文件修改后任务都将执行有,可能并发执行
watch('src/*.js', { queue: false }, function(cb) {   
//...
  cb();
});

4、延迟
文件更改之后,有 200 毫秒的延迟,文件监控程序所关联的任务(task)才会被执行。这是为了避免在同时更改多文件时(例如查找和替换操作)过早启动任务(taks)的执行。
如需调整延迟时间,请为 delay 参数设置一个正整数。

const { watch } = require('gulp');
// 文件修改后等待 500 毫秒执行任务
watch('src/*.js', { delay: 500 }, function(cb) {   
//...
  cb();
});

你可能感兴趣的:(gulp 笔记 要点概况)