前言
Gulp
是一个非常流行且强大的自动化构建工具。它可以将开发流程中需要重复操作的任务自动化,提高我们的开发效率。
基础使用
Gulp
将我们开发流程中需要重复执行的操作定义成一个个任务。
yarn init --yes
,创建一个 node 项目。yarn add gulp --dev
,安装开发依赖 gulp。code gulpfile.js
。在 vscode IDE 中创建一个gulpfile.js
文件并编辑。该文件是 gulp 的入口文件。内容如下:
// 创建一个 foo 任务
exports.foo = (done) => {
console.log("foo task working...");
done(); // 标识任务完成
};
// 名称为 default 的任务会默认执行
exports.default = (done) => {
console.log("default task working...");
done();
};
- 执行任务
yarn gulp foo
:执行 foo 任务yarn gulp
:执行默认任务名为default
的任务
组合任务
组合任务允许我们控制一组任务的串行执行和并发执行。主要使用 series
和 parallel
这两个 api。
const { series, parallel } = require("gulp");
const task1 = (done) => {
setTimeout(() => {
console.log("task1 working...");
done();
}, 1000);
};
const task2 = (done) => {
setTimeout(() => {
console.log("task2 working...");
done();
}, 1000);
};
const task3 = (done) => {
setTimeout(() => {
console.log("task3 working...");
done();
}, 1000);
};
// 串行
exports.foo = series(task1, task2, task3);
// 并行
exports.bar = parallel(task1, task2, task3);
- 串行执行:yarn gulp foo
- 并行执行:yarn gulp bar
异步任务
处理异步任务的核心思想就是需要告诉 gulp
,当前任务何时结束。在 gulp
中可以通过 done
回调调用,异步任务可在方法中返回 promise
、stream
等对象来实现。
done 回调方式
exports.callback = (done) => {
console.log("callback task...");
done();
};
exports.callback_error = (done) => {
console.log("callback_error task...");
done(new Error("callback task failed!!!"));
};
promise 方式
exports.promise = () => {
console.log("promise task...");
return Promise.resolve();
};
exports.promise_error = () => {
console.log("promise task failed!!!");
return Promise.reject(new Error("promise error"));
};
结合 async
语法使用
const timeout = (time) => {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
};
exports.async = async () => {
await timeout(1000);
console.log("async task...");
};
stream 方式
const fs = require("fs");
exports.stream = () => {
const readStream = fs.createReadStream("package.json");
const writeStream = fs.createWriteStream("temp.txt");
readStream.pipe(writeStream);
return readStream;
};
exports.streamWithDone = (done) => {
const readStream = fs.createReadStream("package.json");
const writeStream = fs.createWriteStream("temp.txt");
readStream.pipe(writeStream);
// 返回 stream 对象后,gulp 会监听文件流的 end 事件,成功后会再回调 done
readStream.on("end", () => {
done();
});
};
工作原理
gulp
的核心原理就是对文件的流式操作,过程主要是:输入流->转换流->输出流。我们保留 gulp
的入口文件,在 gulpfile.js
文件中使用 node 的文件 api 来模拟这一个过程。
const fs = require("fs");
const { Transform } = require("stream");
exports.default = () => {
/**
* 1. 创建文件读取流、写入流
* 2. 将读取流内容导入到写入流
* 3. 创建文件转换流
*/
const read = fs.createReadStream("normalize.css");
const write = fs.createWriteStream("normalize.min.css");
const transform = new Transform({
transform: (chunk, encoding, callback) => {
// 转换过程
// 通过 chunk 读取流中的 Buffer
const input = chunk.toString();
const output = input.replace(/\s+/g, "").replace(///*.+?*//g, "");
callback(null, output);
},
});
// 流式过程
read.pipe(transform).pipe(write);
return read;
};
文件操作 API
gulp 中扩展了 Node 的 stream
api。
const { src, dest } = require("gulp");
const cleanCss = require("gulp-clean-css");
const rename = require("gulp-rename");
exports.default = () => {
return src("src/*.css")
.pipe(cleanCss())
.pipe(rename({ extname: ".min.css" }))
.pipe(dest("dist"));
};