掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
gulp是基于流(stream)的自動(dòng)化構(gòu)建工具。

目前創(chuàng)新互聯(lián)已為近千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計(jì)、吉安網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
如果之前已經(jīng)全局安裝了 gulp ,請(qǐng)通過(guò)運(yùn)行以下命令來(lái)刪除舊安裝:
- npm rm --global gulp
然后通過(guò)以下命令安裝獨(dú)立的gulp-cli
- npm i --global gulp-cli
為什么廢棄gulp,而改用gulp-cli?
想將cli和gulp進(jìn)行解耦,處理只位于gulp-cli中。目的:
看一下安裝的版本2.x
- gulp -v
- CLI version: 2.3.0
- Local version: Unknown
進(jìn)入到項(xiàng)目中,安裝gulp
- npm i --save-dev gulp
執(zhí)行g(shù)ulp -v
- chengxinsong$ gulp -v
- CLI version: 2.3.0
- Local version: 4.0.2
在項(xiàng)目的根目錄下創(chuàng)建gulpfile.js文件,在文件中輸入以下內(nèi)容:
- function defaultTask(cb) {
- cb();
- }
- exports.default = defaultTask;
- const gulp = require('gulp');
- const uglify = require('gulp-uglify');
- gulp.task('gulpSaucxs', function(done) {
- gulp.src('src/*.js') // dist與src在共同目錄下
- .pipe(uglify())
- .pipe(gulp.dest('dist/js')); // 相對(duì)路徑
- done();
- })
上面代碼中,task方法接收的是任務(wù)代碼,接收的必須有回調(diào)函數(shù),gulp.src()方法去找src目錄下的js文件,.pipe是接收一個(gè)流的結(jié)果,并返回一個(gè)處理后流的結(jié)構(gòu),pipe方法中執(zhí)行uglifg()方法用來(lái)壓縮js代碼。gulp.dest()方法輸出到指定相對(duì)目錄下。done()方法就是回調(diào)函數(shù)執(zhí)行。
我們?cè)趕rc下新建一個(gè)index.js文件,我們來(lái)寫(xiě)最長(zhǎng)遞增子序列的方法。
- // 最長(zhǎng)遞增子序列
- function lis(n) {
- if (n.length === 0) return 0
- // 創(chuàng)建一個(gè)和參數(shù)相同大小的數(shù)組,并填充值為 1
- let array = new Array(n.length).fill(1)
- // 從索引 1 開(kāi)始遍歷,因?yàn)閿?shù)組已經(jīng)所有都填充為 1 了
- for (let i = 1; i < n.length; i++) {
- for (let j = 0; j < i; j++) {
- if (n[i] > n[j]) {
- array[i] = Math.max(array[i], 1 + array[j])
- }
- }
- }
- let res = 1
- for (let i = 0; i < array.length; i++) {
- res = Math.max(res, array[i])
- }
- return res
- }
輸出的已經(jīng)通過(guò)gulp處理的index.js的方法
我們?cè)谂cgulpfile.js的同級(jí)目錄下執(zhí)行g(shù)ulp task的名稱
- gulp gulpSaucxs
gulp后面跟著的是任務(wù)的名稱,不輸入任務(wù)名稱的話會(huì)默認(rèn)找default任務(wù),找不到會(huì)報(bào)錯(cuò)
然后在與src同級(jí)新增dist/js,然后生成壓縮之后index.js文件。
官網(wǎng)說(shuō)是這個(gè)task的API不再是推薦的模式。
那還是簡(jiǎn)單提2句,這個(gè)api伴隨著開(kāi)發(fā)而消失。
- gulp.task(name[, deps], fn)
每個(gè)gulp任務(wù)task都是一個(gè)異步的js函數(shù)。接收一個(gè)回調(diào)函數(shù)作為參數(shù),或者是一個(gè)返回 stream,promise,event emitter、child process 或 observable 類型值的函數(shù)。
我們繼續(xù)改寫(xiě)上面 gulpSaucxs 的任務(wù)。
- const gulp = require('gulp');
- const uglify = require('gulp-uglify');
- function gulpSaucxs(done) {
- gulp.src('src/*.js') // dist與src在共同目錄下
- .pipe(uglify())
- .pipe(gulp.dest('dist/js')); // 相對(duì)路徑
- done();
- }
- exports.gulpSaucxs = gulpSaucxs; // gulpSaucxs函數(shù)被exports導(dǎo)出是公開(kāi)任務(wù),可以直接被gulp命令直接調(diào)用。
導(dǎo)出的 gulpSaucxs 我們可以直接使用gulp命令來(lái)執(zhí)行。
- gulp gulpSaucxs
輸出跟最初是一致的。
被gulpfile導(dǎo)出export的任務(wù)為公開(kāi)任務(wù),未被導(dǎo)出的任務(wù)會(huì)被認(rèn)為是私有任務(wù)。
還是在剛才的代碼中,我們新增privateTask方法和導(dǎo)出組合任務(wù)。
- const gulp = require('gulp');
- const uglify = require('gulp-uglify');
- function gulpSaucxs(done) {
- gulp.src('src/*.js') // dist與src在共同目錄下
- .pipe(uglify())
- .pipe(gulp.dest('dist/js')); // 相對(duì)路徑
- done();
- }
- // 新增的私有任務(wù)
- function privateTask(done) {
- console.log('hello 「松寶寫(xiě)代碼」')
- }
- exports.gulpSaucxs = gulpSaucxs; // gulpSaucxs函數(shù)被exports導(dǎo)出是公開(kāi)任務(wù),可以直接被gulp命令直接調(diào)用。
- exports.composeTask = gulp.series(gulpSaucxs, privateTask); // 導(dǎo)出組合任務(wù)
上面的代碼中,privateTask 方法就是沒(méi)有被直接導(dǎo)出的方法,稱為私有任務(wù);gulpSaucxs 方法是被導(dǎo)出的方法,稱為公共任務(wù)。
私有任務(wù)的設(shè)計(jì)主要是為了內(nèi)部的使用,通常作為gulp.series()和gulp.paralle()組合的組成部分。
這時(shí)候我們執(zhí)行
- gulp composeTask
執(zhí)行結(jié)果
- gulp-test chengxinsong$ gulp composeTask
- [16:14:52] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [16:14:52] Starting 'composeTask'...
- [16:14:52] Starting 'gulpSaucxs'...
- [16:14:52] Finished 'gulpSaucxs' after 8.32 ms
- [16:14:52] Starting 'privateTask'...
- hello 「松寶寫(xiě)代碼」
- [16:14:52] Finished 'privateTask' after 1.21 ms
- [16:14:52] Finished 'composeTask' after 12 ms
我們看日志,series方法是按照順序執(zhí)行,同步執(zhí)行。
gulp提供了2個(gè)強(qiáng)大的組合方法:series() 和 parallel(),允許將多個(gè)獨(dú)立的任務(wù)組合為一個(gè)更強(qiáng)大的操作。
特點(diǎn):
我們把上面的例子的series方法換成parallel。
- const gulp = require('gulp');
- const uglify = require('gulp-uglify');
- function gulpSaucxs(done) {
- gulp.src('src/*.js') // dist與src在共同目錄下
- .pipe(uglify())
- .pipe(gulp.dest('dist/js')); // 相對(duì)路徑
- done();
- }
- // 新增的私有任務(wù)
- function privateTask(done) {
- console.log('hello 「松寶寫(xiě)代碼」');
- done();
- }
- exports.gulpSaucxs = gulpSaucxs; // gulpSaucxs函數(shù)被exports導(dǎo)出是公開(kāi)任務(wù),可以直接被gulp命令直接調(diào)用。
- exports.composeTask = gulp.parallel(gulpSaucxs, privateTask); // 導(dǎo)出組合任務(wù),以最大的并發(fā)來(lái)運(yùn)行
執(zhí)行
- gulp cpmposeTask
執(zhí)行結(jié)果
- chengxinsong$ gulp composeTask
- [18:24:35] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [18:24:35] Starting 'composeTask'...
- [18:24:35] Starting 'gulpSaucxs'...
- [18:24:35] Starting 'privateTask'...
- [18:24:35] Finished 'gulpSaucxs' after 8.24 ms
- hello 「松寶寫(xiě)代碼」
- [18:24:35] Finished 'privateTask' after 9.71 ms
- [18:24:35] Finished 'composeTask' after 12 ms
我們可以輸出日志,可以知道parallel方法是并行的執(zhí)行任務(wù)
當(dāng)從任務(wù)(task)中返回 stream、promise、event emitter、child process 或 observable 時(shí),成功或錯(cuò)誤值將通知 gulp 是否繼續(xù)執(zhí)行或結(jié)束。如果任務(wù)(task)出錯(cuò),gulp 將立即結(jié)束執(zhí)行并顯示該錯(cuò)誤。
- const gulp = require('gulp');
- const uglify = require('gulp-uglify');
- function streamTask(done) {
- return gulp.src('src/*.js')
- .pipe(uglify())
- .pipe(gulp.dest('dist/js'));
- done();
- }
- exports.streamTask = streamTask;
輸出:dist/js/index.js
看一個(gè)返回promise的例子。
- const gulp = require('gulp');
- function promiseTask(done) {
- Promise.resolve('返回的值');
- done();
- }
- exports.promiseTask = promiseTask;
輸出:
- chengxinsong$ gulp promiseTask
- [19:20:37] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [19:20:37] Starting 'promiseTask'...
- [19:20:37] Finished 'promiseTask' after 1.55 ms
- 返回的值 「松寶寫(xiě)代碼」公眾號(hào)
看一個(gè)返回 eventEmitter 的例子。
- // 返回event emitter
- const { EventEmitter } = require('events');
- function eventEmitterTask(done) {
- const emitter = new EventEmitter();
- setTimeout(() => {
- emitter.emit('data')
- console.log(emitter, '松寶寫(xiě)代碼')
- }, 500);
- done();
- }
- exports.eventEmitterTask = eventEmitterTask;
執(zhí)行 gulp eventEmitterTask,結(jié)果如下:
- chengxinsong$ gulp eventEmitterTask
- [21:42:26] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [21:42:26] Starting 'eventEmitterTask'...
- [21:42:26] Finished 'eventEmitterTask' after 1.77 ms
- EventEmitter {
- _events: [Object: null prototype] {},
- _eventsCount: 0,
- _maxListeners: undefined,
- [Symbol(kCapture)]: false
- } 松寶寫(xiě)代碼
看一個(gè)返回 childProcess 的例子。
- // 返回child_process 子進(jìn)程
- const { exec } = require('child_process');
- function childProcessTask(done) {
- exec('data');
- console.log('松寶寫(xiě)代碼')
- done();
- }
- exports.childProcessTask = childProcessTask;
執(zhí)行 gulp childProcessTask ,結(jié)果如下:
- chengxinsong$ gulp childProcessTask
- [21:48:32] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [21:48:32] Starting 'childProcessTask'...
- 松寶寫(xiě)代碼
- [21:48:32] Finished 'childProcessTask' after 7.02 ms
看一個(gè)返回 observable 的例子。
- // 返回 observable 觀察對(duì)象
- const Observable = require('rx').Observable;
- function observableTask(done) {
- Observable.return('松寶寫(xiě)代碼');
- console.log('松寶寫(xiě)代碼')
- done();
- }
- exports.observableTask = observableTask;
執(zhí)行 gulp observableTask ,結(jié)果如下:
- chengxinsong$ gulp observableTask
- [21:53:14] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [21:53:14] Starting 'observableTask'...
- 松寶寫(xiě)代碼
- [21:53:14] Finished 'observableTask' after 2.28 ms
看一個(gè)使用 callback 回調(diào)函數(shù) 的例子。
如果任務(wù)(task)不返回任何內(nèi)容,則必須使用 callback 來(lái)指示任務(wù)已完成。
如需通過(guò) callback 把任務(wù)(task)中的錯(cuò)誤告知 gulp,將 Error 作為 callback 的參數(shù)。
- // 返回 callback 回調(diào)函數(shù)
- function callbackTask(done) {
- console.log('松寶寫(xiě)代碼')
- done(new Error('拋出錯(cuò)誤了'));
- }
- exports.callbackTask = callbackTask;
執(zhí)行 gulp callbackTask 結(jié)果
- chengxinsong$ gulp callbackTask
- [21:58:22] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [21:58:22] Starting 'callbackTask'...
- 松寶寫(xiě)代碼
- [21:58:22] 'callbackTask' errored after 2.09 ms
- [21:58:22] Error: 拋出錯(cuò)誤了
- at callbackTask
看一個(gè)使用 async/await 異步函數(shù) 的例子。
可以將任務(wù)(task)定義為一個(gè) async 函數(shù),它將利用 promise 對(duì)你的任務(wù)(task)進(jìn)行包裝。這將允許你使用 await 處理 promise,并使用其他同步代碼。
- // 使用 async/await 回調(diào)函數(shù)
- const fs = require('fs');
- async function asyncTask(done) {
- const { version } = fs.readFileSync('package.json');
- console.log(version, 'version=====')
- const data = await Promise.resolve('松寶寫(xiě)代碼');
- console.log(data, '松寶寫(xiě)代碼=========')
- done();
- }
- exports.asyncTask = asyncTask;
執(zhí)行 gulp asyncTask 結(jié)果
- chengxinsong$ gulp asyncTask
- [22:26:06] Using gulpfile ~/Desktop/coding/full_stack_knowledge_list/article/gulp/gulp-test/gulpfile.js
- [22:26:06] Starting 'asyncTask'...
- undefined version=====
- 松寶寫(xiě)代碼 松寶寫(xiě)代碼=========
- [22:26:06] Finished 'asyncTask' after 2.02 ms
比如我們需要
- // 實(shí)例
- const minifycss = require('gulp-minify-css'); //壓縮css
- const del = require('del'); // 刪除目錄
- // 清空目錄
- function clean(done) {
- del(['dist/**']);
- done();
- }
- // 壓縮css
- function minifyCss(done) {
- gulp.src('src/*.css')
- .pipe(minifycss())
- .pipe(gulp.dest('dist/css'));
- done()
- }
- // 壓縮js
- function uglifyJs(done) {
- gulp.src('src/*.js')
- .pipe(uglify())
- .pipe(gulp.dest('dist/js'));
- done();
- }
- exports.exampleGulpTask = gulp.series(clean, gulp.parallel(minifyCss, uglifyJs)); // 執(zhí)行順序 clean => 并行執(zhí)行 css js 壓縮

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流