專案原始碼地址

前期準備工作

安裝 gulp 命令列工具

npm install --global gulp-cli

在專案目錄下建立 package.json 檔案

npm init -y

安裝 gulp,作為開發時依賴項

npm install --save-dev gulp

檢查 gulp 版本

gulp --version
PS D:\a-個人專案管理\使用Gulp搭建專案\gulp-building> gulp --version
CLI version: 2.3.0
Local version: 4.0.2

建立配置檔案

在根目錄下新建 src 資料夾和 gulpfile.js 檔案

src 目錄下新建如下檔案,其中 index.html 作為我們的入口頁面

gulp 中常用方法解釋

src

建立一個流,用於從檔案系統讀取 Vinyl 物件。

函式原型

src(globs, [options])

返回值

返回一個可以在管道的開始或中間使用的流,用於根據給定的 globs 新增檔案。

globs

glob 是由普通字元和/或通配字元組成的字串,用於匹配檔案路徑。可以利用一個或多個 glob 在檔案系統中定位檔案。

src() 方法接受一個 glob 字串或由多個 glob 字串組成的陣列作為引數,用於確定哪些檔案需要被操作。glob 或 glob 陣列必須至少匹配到一個匹配項,否則 src() 將報錯。當使用 glob 陣列時,將按照每個 glob 在陣列中的位置依次執行匹配 - 這尤其對於取反(negative) glob 有用。

特殊字元: * (一個星號)

在一個字串片段中匹配任意數量的字元,包括零個匹配。對於匹配單級目錄下的檔案很有用。

下面這個 glob 能夠匹配類似 index.js 的檔案,但是不能匹配類似 scripts/index.jsscripts/nested/index.js 的檔案。

'*.js'

特殊字元: ** (兩個星號)

在多個字串片段中匹配任意數量的字元,包括零個匹配。 對於匹配巢狀目錄下的檔案很有用。請確保適當地限制帶有兩個星號的 glob 的使用,以避免匹配大量不必要的目錄。

下面這個 glob 被適當地限制在 scripts/ 目錄下。它將匹配類似 scripts/index.jsscripts/nested/index.jsscripts/nested/twice/index.js 的檔案。

'scripts/**/*.js'

desc

dest() 接受一個輸出目錄作為引數,並且它還會產生一個 Node 流(stream),通常作為終止流(terminator stream)。當它接收到通過管道(pipeline)傳輸的檔案時,它會將檔案內容及檔案屬性寫入到指定的目錄中。gulp 還提供了 symlink() 方法,其操作方式類似 dest(),但是建立的是連結而不是檔案( 詳情請參閱 symlink() )。

大多數情況下,利用 .pipe() 方法將外掛放置在 src()dest() 之間,並轉換流(stream)中的檔案。

series

將任務函式和/或組合操作組合成更大的操作,這些操作將按順序依次執行。對於使用 series()parallel() 組合操作的巢狀深度沒有強制限制。

用法

const { series } = require('gulp');

function javascript(cb) {
// body omitted
cb();
} function css(cb) {
// body omitted
cb();
} exports.build = series(javascript, css);

parallel

將任務功能和/或組合操作組合成同時執行的較大操作。對於使用 series()parallel() 進行巢狀組合的深度沒有強制限制。

用法

const { parallel } = require('gulp');

function javascript(cb) {
// body omitted
cb();
} function css(cb) {
// body omitted
cb();
} exports.build = parallel(javascript, css);

watch

監聽 globs 並在發生更改時執行任務。任務與任務系統的其餘部分被統一處理。

用法

const { watch } = require('gulp');

watch(['input/*.js', '!input/something.js'], function(cb) {
// body omitted
cb();
});

啟動專案並熱更新

安裝

npm install --save-dev browser-sync

使用

gulpfile.js 檔案中配置如下程式碼

const { series, parallel, src, dest, watch } = require("gulp");
const browserSync = require("browser-sync"); // 啟動專案
const reload = browserSync.reload; // 更新頁面 // 啟動專案
function server() {
browserSync({
notify: false, // 關閉通知,頁面右上角不會出現彈框
port: 3000, // 啟動 3000 埠
server: {
baseDir: ["src"], // 配置根目錄,在這個根目錄下啟動伺服器
},
callbacks: {
// 專案啟動成功後執行的方法
ready: () => {
console.log("開始監控開發資料夾");
// 設定要監控的頁面,當被監控頁面發生變化時執行過載方法
const watcher = watch(["src/**/*.html", "src/**/*.js", "src/**/*.css"]);
// 監聽到變化後執行
watcher.on("change", () => {
// 頁面變化後執行過載方法
reload();
});
},
},
});
} // 公開 server 任務,執行 gulp server 執行啟動任務
exports.server = server;

執行

然後在控制檯中執行 gulp server

執行成功如上圖所示,同時自動瀏覽器

壓縮 HTML

安裝

npm install --save-dev gulp-htmlmin gulp-html-replace

配置

下面用到的 gulp-html-replace 替換檔案引用地址,我們需要在 html 中需要替換的地方通過註釋形式來告訴配置檔案我要替換那個地址

標記格式,標記後我們就可以通過標記的名稱來對引用地址進行替換

<!-- build:css -->
<link rel="stylesheet" href="./public/css/index.css">
<!-- endbuild --> <!-- build:js -->
<script src="./public/js/index.js"></script>
<!-- endbuild -->

配置程式碼

const { series, parallel, src, dest, watch } = require("gulp");
const htmlmin = require("gulp-htmlmin"); // 壓縮html
const htmlreplace = require("gulp-html-replace"); // 替換檔案引用地址
// 配置壓縮html的規則
const indexOptions = {
removeComments: true, // 清除html註釋
collapseWhitespace: true, // 壓縮html
collapseBooleanAttributes: true, //省略布林屬性的值 <input checked="true"/> -> <input checked />
removeEmptyAttributes: true, // 刪除所有空格作為屬性值 <inpit id=""/> -> <inpit/>
minifyCss: true, // 壓縮頁面中的css
minifyJs: true, // 壓縮頁面中的js
}; // 壓縮打包html
function html() {
return src(["src/view/**/*.html"])
.pipe(htmlmin(indexOptions)) // 使用上面定義的壓縮配置進行壓縮html
.pipe(dest("dist/html/")); // 將檔案寫入到 dist/html/ 目錄下
}
// 單獨處理一下 index.html
function indexhtml() {
return src("src/index.html")
.pipe(
htmlreplace({
// 替換標記的路徑
css: "css/index.css",
js: "js/index.min.js",
})
)
.pipe(htmlmin(indexOptions)) // 使用上面定義的壓縮配置進行壓縮html
.pipe(dest("dist/"));
}

壓縮 CSS

安裝

npm install --save-dev gulp-csso @babel/core

配置

const { series, parallel, src, dest, watch } = require("gulp");
const csso = require("gulp-csso"); // 壓縮css // 壓縮css
function css() {
return src("src/public/css/**/*.css").pipe(csso()).pipe(dest("dist/css"));
}

壓縮 JS

安裝

npm install --save-dev gulp-uglify gulp-babel gulp-rename gulp-string-replace

配置

const { series, parallel, src, dest, watch } = require("gulp");
const babel = require("gulp-babel"); // 支援es6以及模組化
const uglify = require("gulp-uglify"); // 壓縮js程式碼
const rename = require("gulp-rename"); // 重新命名檔案
const replace = require("gulp-string-replace"); // 替換字串 // 壓縮js
function js() {
// 即使這個任務不需要回調,但也要有一個預設的回撥方法,也可以return
// cb();
return src("src/public/js/*.js")
.pipe(babel())
.pipe(uglify()) // 壓縮js程式碼
.pipe(replace(/assetApi/g, "https://www.gulpjs.com.cn")) // 替換程式碼中的 "assetApi"
.pipe(rename({ extname: ".min.js" })) // 將匹配到的檔案重名名為xxx.main.js
.pipe(dest("dist/js/")); // 將檔案寫入到 dist/js/ 目錄下
}

清空檔案

安裝

npm install --save-dev gulp-clean

配置

const { series, parallel, src, dest, watch } = require("gulp");
const clean = require("gulp-clean"); // 清空資料夾 // 清空dist資料夾
function cleans() {
// 獲取到dist資料夾下面的所有檔案,進行清空操作
return src(["./dist/*"]).pipe(clean());
}

打包程式碼

新建打包任務

/**
* 打包任務
* 私有任務也可以在 series 組合中使用
* series 是順序執行多個任務
* parallel 是平行執行多個任務
*/
const build = series(cleans, js, html, indexhtml, css, function (cb) {
// 必須要有一個回撥方法
cb();
}); // 公開 build 任務,執行 gulp build 執行打包任務
exports.build = build;

在控制檯執行 gulp build

執行成功後會在根目錄下自動生成一個 dist 資料夾

我們開啟打包好的檔案,可以看到配置的一些規則都是生效的

我們在檔案中直接雙擊開啟 dist/index.html

頁面可以正常的顯示出來,表示路徑的引用也是正確的

完整的開發依賴包

"devDependencies": {
"@babel/core": "^7.14.3",
"browser-sync": "^2.26.14",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean": "^0.4.0",
"gulp-csso": "^4.0.1",
"gulp-html-replace": "^1.6.2",
"gulp-htmlmin": "^5.0.1",
"gulp-rename": "^2.0.0",
"gulp-string-replace": "^1.1.2",
"gulp-uglify": "^3.0.2",
"gulp-webserver": "^0.9.1"
}

完整的配置程式碼

const { series, parallel, src, dest, watch } = require("gulp");
const babel = require("gulp-babel"); // 支援es6以及模組化
const uglify = require("gulp-uglify"); // 壓縮js程式碼
const rename = require("gulp-rename"); // 重新命名檔案
const clean = require("gulp-clean"); // 清空資料夾
const csso = require("gulp-csso"); // 壓縮css
const htmlmin = require("gulp-htmlmin"); // 壓縮html
const gulpServer = require("gulp-webserver"); // 啟動專案
const htmlreplace = require("gulp-html-replace"); // 替換檔案引用地址
const replace = require("gulp-string-replace"); // 替換字串
const browserSync = require("browser-sync"); // 啟動專案
const reload = browserSync.reload; // 更新頁面 // 配置壓縮html的規則
const indexOptions = {
removeComments: true, // 清除html註釋
collapseWhitespace: true, // 壓縮html
collapseBooleanAttributes: true, //省略布林屬性的值 <input checked="true"/> -> <input checked />
removeEmptyAttributes: true, // 刪除所有空格作為屬性值 <inpit id=""/> -> <inpit/>
minifyCss: true, // 壓縮頁面中的css
minifyJs: true, // 壓縮頁面中的js
}; // 清空dist資料夾
function cleans() {
// 獲取到dist資料夾下面的所有檔案,進行清空操作
return src(["./dist/*"]).pipe(clean());
} // 壓縮js
function js() {
// 即使這個任務不需要回調,但也要有一個預設的回撥方法,也可以return
// cb();
return src("src/public/js/*.js")
.pipe(babel())
.pipe(uglify()) // 壓縮js程式碼
.pipe(replace(/assetApi/g, "https://www.gulpjs.com.cn")) // 替換程式碼中的 "assetApi"
.pipe(rename({ extname: ".min.js" })) // 將匹配到的檔案重名名為xxx.main.js
.pipe(dest("dist/js/")); // 將檔案寫入到 dist/js/ 目錄下
} // 壓縮打包html
function html() {
return src(["src/view/**/*.html"])
.pipe(htmlmin(indexOptions)) // 使用上面定義的壓縮配置進行壓縮html
.pipe(dest("dist/html/")); // 將檔案寫入到 dist/html/ 目錄下
} // 單獨處理一下 index.html
function indexhtml() {
return src("src/index.html")
.pipe(
htmlreplace({
// 從註釋標記中獲取要替換的路徑
css: "css/index.css",
js: "js/index.min.js",
})
)
.pipe(htmlmin(indexOptions)) // 使用上面定義的壓縮配置進行壓縮html
.pipe(dest("dist/"));
} // 壓縮css
function css() {
return src("src/public/css/**/*.css").pipe(csso()).pipe(dest("dist/css"));
} // 啟動專案
function server() {
browserSync({
notify: false, // 關閉通知,頁面右上角不會出現彈框
port: 3000, // 啟動 3000 埠
server: {
baseDir: ["src"], // 配置根目錄,在這個根目錄下啟動伺服器
},
callbacks: {
// 專案啟動成功後執行的方法
ready: () => {
console.log("開始監控開發資料夾");
// 設定要監控的頁面,當被監控頁面發生變化時執行過載方法
const watcher = watch(["src/**/*.html", "src/**/*.js", "src/**/*.css"]);
// 監聽到變化後執行
watcher.on("change", () => {
// 頁面變化後執行過載方法
reload();
});
},
},
});
} /**
* 打包任務
* 私有任務也可以在 series 組合中使用
* series 是順序執行多個任務
* parallel 是平行執行多個任務
*/
const build = series(cleans, js, html, indexhtml, css, function (cb) {
// 必須要有一個回撥方法
cb();
}); // 公開 server 任務,執行 gulp server 執行啟動任務
exports.server = server;
// 公開 build 任務,執行 gulp build 執行打包任務
exports.build = build;