使用gulp助力前端自動化

2022-07-29 12:01:07

前言

隨著前端諸如webpack,rollup,vite的發展,gulp感覺似乎好像被取代了。其實並沒有,只不過它從臺前退居到了幕後。我們仍然可以在很多專案中看到它的身影,比如elementplus、vant等。現在gulp更多的是做流程化的控制。

比如我們要把一個大象放進冰箱裡就需要 開啟冰箱門->把大象放進冰箱->關上冰箱門,這就是一個簡單的流程,使用gulp就可以規定這些流程,將這個流程自動化,並自動執行這個流程。

所以我們可以使用它在專案開發過程中自動執行常見任務。比如打包一個元件庫,我們可能要移除檔案、copy檔案,打包樣式、打包元件、執行一些命令還有一鍵打包多個package等等都可以由gulp進行自定義流程的控制,非常的方便。

本文將主要介紹gulp的一些常用功能

安裝gulp

首先全域性安裝gulp的腳手架

npm install --global gulp-cli

然後我們新建資料夾gulpdemo,然後執行 npm init -y,然後在這個專案下安裝本地依賴gulp

npm install gulp -D    

此時我們gulp便安裝好了,接下來我們在根目錄下建立gulpfile.js檔案,當gulp執行的時候會自動尋找這個檔案。

建立一個任務Task

每個gulp任務(task)都是一個非同步的JavaScript函數,此函數是一個可以接收callback作為引數的函數,或者返回一個Promise等非同步操作物件,比如建立一個任務可以這樣寫

exports.default = (cb) => {
  console.log("my task");
  cb();
};

或者這樣寫

exports.default = () => {
  console.log("my task");
  return Promise.resolve();
};

然後終端輸入gulp就會執行我們這個任務

序列(series)和並行(parallel)

這兩個其實很好理解,序列就是任務一個一個執行,並行就是所有任務一起執行。下面先看序列演示

const { series, parallel } = require("gulp");

const task1 = () => {
  console.log("task1");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 5000);
  });
};
const task2 = () => {
  console.log("task2");
  return Promise.resolve();
};

exports.default = series(task1, task2);

控制檯輸出結果如下

可以看出執行task1用了5s,然後再執行task2,再看下並行

const { series, parallel } = require("gulp");

const task1 = () => {
  console.log("task1");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 5000);
  });
};
const task2 = () => {
  console.log("task2");
  return Promise.resolve();
};

exports.default = parallel(task1, task2);


可以看出兩個任務是同時執行的

src()和dest()

src()和dest()這兩個函數在我們實際專案中經常會用到。src()表示建立一個讀取檔案系統的流,dest()是建立一個寫入到檔案系統的流。我們直接寫一個copy 的範例

複製

在寫之前我們先在我們專案根目錄下新建一個src目錄用於存放我們被複制的檔案,在src下隨便新建幾個檔案,如下圖

然後我們在gulpfile.js寫下我們的copy任務:將src下的所有檔案複製到dist資料夾下

const { src, dest } = require("gulp");

const copy = () => {
  return src("src/*").pipe(dest("dist/"));
};

exports.default = copy;

然後執行gulp(預設執行exports.default),我們就會發現根目錄下多了個dist資料夾

處理less檔案

下面我們寫個處理less檔案的任務,首先我們先安裝gulp-less

npm i -D gulp-less
然後我們在src下新建一個style/index.less並寫下一段less語法樣式
@color: #fff;
.wrap {
  color: @color;
}

然後gulpfile.js寫下我們的lessTask:將我們style下的less檔案解析成css並寫入dist/style中

const { src, dest } = require("gulp");
const less = require("gulp-less");
const lessTask = () => {
  return src("src/style/*.less").pipe(less()).pipe(dest("dist/style"));
};

exports.default = lessTask;

然後我們執行gulp命令就會發現dist/style/index.css

.wrap {
  color: #fff;
}

我們還可以給css加字首

npm install gulp-autoprefixe -D

將我們的src/style/index.less改為

@color: #fff;
.wrap {
  color: @color;
  display: flex;
}

然後在gulpfile.js中使用gulp-autoprefixe

const { src, dest } = require("gulp");
const less = require("gulp-less");
const autoprefixer = require("gulp-autoprefixer");
const lessTask = () => {
  return src("src/style/*.less")
    .pipe(less())
    .pipe(
      autoprefixer({
        overrideBrowserslist: ["> 1%", "last 2 versions"],
        cascade: false, //  是否美化屬性值
      })
    )
    .pipe(dest("dist/style"));
};

exports.default = lessTask;

處理後的dist/style/index.css就變成了

.wrap {
  color: #fff;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

監聽檔案更改browser-sync

browser-sync是一個十分好用的瀏覽器同步測試工具,它可以搭建靜態伺服器,監聽檔案更改,並重新整理頁面(HMR),下面來看下它的使用

首先肯定要先安裝

npm i browser-sync -D 

然後我們在根目錄下新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
        hello world
</body>
</html>

然後在gulpfile.js中進行設定

const browserSync = require("browser-sync");
const browserTask = () => {
  browserSync.init({
    server: {
      baseDir: "./",
    },
  });
};

exports.default = browserTask;


這時候就會啟動一個預設3000埠的頁面. 下面我們看如何監聽頁面變化。

首先我們要監聽檔案的改變,可以使用browserSync的watch,監聽到檔案改變後再重新整理頁面

const { watch } = require("browser-sync");
const browserSync = require("browser-sync");
const { series } = require("gulp");

const reloadTask = () => {
  browserSync.reload();
};

const browserTask = () => {
  browserSync.init({
    server: {
      baseDir: "./",
    },
  });
  watch("。/*", series(reloadTask));
};

exports.default = browserTask;

此時改動src下的檔案瀏覽器便會重新整理。

下面我們將index.html引入dist/style/index.css的樣式,然後來模擬一個簡單的構建流

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="../dist/style/index.css" />
  </head>
  <body>
    <div class="wrap">hello world</div>
  </body>
</html>


此時我們的流程是 編譯less檔案->將css寫入dist/style->觸發頁面更新

我們gulpfile.js可以這樣寫

const { src, dest } = require("gulp");
const { watch } = require("browser-sync");
const browserSync = require("browser-sync");
const { series } = require("gulp");
const less = require("gulp-less");
const autoprefixer = require("gulp-autoprefixer");
const lessTask = () => {
  return src("src/style/*.less")
    .pipe(less())
    .pipe(
      autoprefixer({
        overrideBrowserslist: ["> 1%", "last 2 versions"],
        cascade: false, //  是否美化屬性值
      })
    )
    .pipe(dest("dist/style"));
};
//頁面重新整理
const reloadTask = () => {
  browserSync.reload();
};

const browserTask = () => {
  browserSync.init({
    server: {
      baseDir: "./",
    },
  });
  watch("./*.html", series(reloadTask));
  //監聽樣式更新觸發兩個任務
  watch("src/style/*", series(lessTask, reloadTask));
};

exports.default = browserTask;

此時無論我們更改的是樣式還是html都可以觸發頁面更新。

最後

後面我會將正在開發的vue3元件庫的樣式打包部分使用gulp處理,如果你對元件庫開發感興趣的話可以關注我,後續會實現一些常用元件,並以文章形式呈現。

創作不易,你的點贊就是我的動力!如果感覺這篇文章對你有幫助的話就請點個贊吧,感謝~