gulp使用指南

一顆冰淇淋發表於2022-11-24

gulp 是一個使用“流”來實現自動化的工具,正如 官方文件 首頁展示的這副動圖一樣,以“流動”的狀態去處理 TypeScript、PNG、Markdown 資源。

與webpack比較

類別webpackgulp
核心理念module bundlertask runner
執行任務模組化定義任務、等待執行
構建方式loader檔案Stream
支援外掛

gulp 相比 webpack 思想會更加簡單、易用,更適合一些自動化任務(比如Jquery、編譯檔案上傳到伺服器等功能),但它預設不支援模組化,所以大型的專案(Vue、React、Angle)並不會使用它。

執行任務

安裝依賴

webpack 一樣,gulp 可以全域性安裝,也可以在專案區域性安裝,這裡透過 npm install gulp 僅在當前專案安裝

配置檔案

webpack 中預設的配置檔案為 webpack.config.js,而 gulp 中預設配置檔案為 gulpfile.js,根目錄建立檔案,定義一個函式,將它匯出,這就定義了一個簡單的任務。

const foo = () => {
  console.log('foo');
};

module.exports = {
  foo,
};
編譯檔案

執行 npx gulp foo 命令編譯任務,在 gulp 後面跟上函式名 foo 告知執行的任務名稱

但此時編譯會報錯,提醒任務沒有完成,是否忘記了傳送非同步任務完成的訊號

非同步任務

這是因為預設情況所有任務是非同步的,想要結束有兩種方式

  1. 返回固定的內容,stream、promise、event emitter、child process 或 observable 型別
  2. 接受一個 callback 作為引數,呼叫 callback 函式任務結束

這裡使用第二種方式

const foo = (cb) => {
  console.log('foo');
  cb();
};

再次執行 npx gulp foo,此時編譯成功,執行時間 2.59ms

預設任務

上面執行命令時,gulp 後面跟了任務名稱 foo,如果不跟名稱時,執行的是預設任務,需要在 gulpfile.js 中匯出預設任務

module.exports.default = (cb) => {
  console.log('default task');
  cb();
};

此時可以看到輸出預設任務

序列並行

當存在多個任務需要進行組合時,可以透過 gulp 提供的方法,series 表示序列,parallel 表示並行。

const { series, parallel } = require('gulp');
const task1 = (cb) => {
  setTimeout(() => {
    console.log('task1');
    cb();
  }, 2000);
};

const task2 = (cb) => {
  setTimeout(() => {
    console.log('task2');
    cb();
  }, 2000);
};

const task3 = (cb) => {
  setTimeout(() => {
    console.log('task3');
    cb();
  }, 2000);
};

const seriesTask = series(task1, task2, task3);
const parallelTask = parallel(task1, task2, task3);
module.exports = {
  seriesTask,
  parallelTask,
};

序列會等上一個任務執行完成,再執行下一個,任務的完成時間為所有任務的總和,並行就會將所有任務一起執行。

讀取檔案、監聽

在專案的 src 資料夾下定義 index.js 檔案,透過 gulp 暴露的 src()dest() 方法用於處理計算機上存放的檔案。

const { src, dest } = require('gulp');
const task = () => {
  return src('src/*.js').pipe(dest('dist'));
};
module.exports = {
  task,
};

此時src資料夾下的 index.js 檔案被讀取到 dist 資料夾下

此時的 js 程式碼沒有做 es6 - es5 的轉化,也沒有壓縮,想要達到這些效果,需要使用 gulp 的外掛,分別是 gulp-babelgulp-terser,定義方式和 webpack 中 babel 和 terser是一致的,不太瞭解 babelterser 的朋友可以點連結檢視。

需注意,使用 gulp-babel 需要安裝 babel 的核心庫 @babel/core 以及指定編譯規則用到的預設 @babel/preset-env 或者其它外掛。

const { src, dest } = require('gulp');
const babel = require('gulp-babel');
const terser = require('gulp-terser');

const task = () => {
  return src('src/*.js')
    .pipe(babel({ presets: ['@babel/preset-env'] }))
    .pipe(terser({ mangle: { toplevel: true } }))
    .pipe(dest('dist'));
};

module.exports = {
  task,
};

透過 pipe() 處理完資源返回一個“流”檔案交給下一個外掛處理,此時 dist 文夾下的 index.js 資源就進行了程式碼轉換和壓縮。

webpack 在編譯的時候提供了 --watch 屬性,當原始碼資源發生變化時,自動重新編譯,gulp 也提供這樣的功能,使用 watch() 來實現。

const { watch } = require('gulp');
watch('src/*.js', task);

使用 watch 後,編譯不會結束,每當監聽的檔案修改並儲存時,重新編譯。

總結

  • gulp 主要以“流”的方式來處理資源,沒有模組化,不適合大型專案。
  • gulp 每次處理即開啟非同步任務,可以並行、序列、監聽資源的更新。
  • 使用外掛,gulp 也能實現程式碼轉化、壓縮等功能。

以上就是 gulp 的介紹, 更多有關 前端工程化 的內容可以參考我其它的博文,持續更新中~