自动化构建工具(一):Gulp 入门

354 阅读2分钟

前言

Gulp 是一个非常流行且强大的自动化构建工具。它可以将开发流程中需要重复操作的任务自动化,提高我们的开发效率。

基础使用

Gulp 将我们开发流程中需要重复执行的操作定义成一个个任务。

  1. yarn init --yes,创建一个 node 项目。
  2. yarn add gulp --dev,安装开发依赖 gulp。
  3. 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();
};
  1. 执行任务
  • yarn gulp foo:执行 foo 任务
  • yarn gulp:执行默认任务名为 default 的任务

组合任务

组合任务允许我们控制一组任务的串行执行和并发执行。主要使用 seriesparallel 这两个 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 回调调用,异步任务可在方法中返回 promisestream 等对象来实现。

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"));
};