gulp 是一個使用“流”來實現自動化的工具,正如 官方文件 首頁展示的這副動圖一樣,以“流動”的狀態去處理 TypeScript、PNG、Markdown 資源。
與webpack比較
類別 | webpack | gulp |
---|---|---|
核心理念 | module bundler | task 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 告知執行的任務名稱
但此時編譯會報錯,提醒任務沒有完成,是否忘記了傳送非同步任務完成的訊號
非同步任務
這是因為預設情況所有任務是非同步的,想要結束有兩種方式
- 返回固定的內容,stream、promise、event emitter、child process 或 observable 型別
- 接受一個 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-babel
和 gulp-terser
,定義方式和 webpack
中 babel 和 terser是一致的,不太瞭解 babel 和 terser 的朋友可以點連結檢視。
需注意,使用 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
的介紹, 更多有關 前端
、工程化
的內容可以參考我其它的博文,持續更新中~