Gulp官網javascript
gulp4.0分離了cli和核心部分,因此須要分別安裝這兩個包,另外對環境要求以下:css
node >= 8.11.1 npm >= 5.6.0 npx >= 9.7.1
npm i -g gulp-cli
npm i -D gulp
$ gulp -v # 輸出 CLI version: 2.2.0 Local version: 4.0.2
在項目根目錄建立gulpfile.js
文件(若是使用ts或者babel,也可用gulpfile.ts
、gulpfile.babel.js
分別代替),此文件即gulp會默認讀取的配置文件,咱們能夠在裏面配置須要的task。
若是task較多或者較複雜,能夠建立gulpfile.js
目錄,在目錄中拆分task爲多個文件,只要保證該目錄下有個index.js
做爲入口便可。html
task分爲兩種:java
const { series, parallel } = require('gulp'); // Private tasks function clean(cb) { // body omitted cb(); } // Private tasks function build(cb) { // body omitted cb(); } exports.build = build; // Public tasks, 執行gulp build exports.default = series(clean, parallel(css, javascript)); // Public tasks, 執行gulp
注意:
在task中,操做完成時,咱們必需要經過cb()或者return的方式來告知gulp此任務已完成。node
// cb function clean(cb) { del(['dist]); cb(); }); // return function minifyjs() { return src('src/**/*.js') .pipe(minify()) .pipe(dest('dist')); }); function promiseTask() { return new Promise(function(resolve, reject) { // body omitted resolve(); }); });
gulp <export task name> gulp // 導出爲default的task能夠直接運行gulp
// task1執行完再執行task2 exports.taskName = series(task1, task2)
// task1和task2同時執行 exports.taskName = parallel(task1, task2)
exports.taskName = series(clean, parallel(css, javascript))
gulp借鑑了Unix的管道(pipe)思想,處理文件採用流的方式,前一步的輸出做爲後一步的輸入,中途不會在磁盤寫入文件,僅在dest時輸出文件,因此很是快速高效。webpack
gulp提供了src及dest方法分別來進行文件讀入、輸出操做,同時提供了pipe管道方法來鏈式執行其餘操做。web
const { src, dest } = require('gulp'); // 將src目錄下的全部js輸出到output目錄 exports.default = function() { return src('src/*.js') .pipe(dest('output/')); }
若是咱們想在中途添加文件能夠採用以下方式:npm
const { src, dest } = require('gulp'); const uglify = require('gulp-uglify'); exports.default = function() { return src('src/*.js') .pipe(uglify()) .pipe(src('vendor/*.js')) // 添加文件 .pipe(dest('output/')); }
固然咱們也能夠進行屢次輸出:gulp
const { src, dest } = require('gulp'); const babel = require('gulp-babel'); const uglify = require('gulp-uglify'); exports.default = function() { return src('src/*.js') .pipe(babel()) .pipe(dest('temp/')) .pipe(uglify()) .pipe(dest('output/')); }
每每咱們在使用src方法的時候須要輸入多個或者一類文件,而不只僅是某個具體的文件,這時咱們就可使用gulp提供的匹配規則來處理。c#
"src/file.js"
:單個文件["src/file1,src/file2.js"]
:多個文件*
: 全部文件src('src/*.js') // src自身目錄全部的js文件,不含後代文件夾中 src('src/a*c.js')
**
:0或者多個文件夾src('src/**/*.js') // src目錄全部的js文件,含後代文件夾中的
{}
:多個屬性src('src/*.{jpg,png,gif}') // src自身目錄下的全部jpg、png和gif文件
!
:排除src(['**/*.js', '!node_modules/**']) // 全部的js文件,可是node_modules下的除外
注意:src 接收的文件匹配字符串會順序解釋,因此你能夠寫成這樣 gulp.src(['.js', '!b.js', 'bad.js'])
(排除全部以 b 開頭的 JS 文件可是除了 bad.js
)
gulp推薦每一個插件應該只專一的作一小部分工做,而後經過pipe將它們鏈接起來,就能夠完成咱們須要作的事情。
const { src, dest } = require('gulp'); const uglify = require('gulp-uglify'); const rename = require('gulp-rename'); exports.default = function() { return src('src/*.js') // The gulp-uglify plugin won't update the filename .pipe(uglify()) // So use gulp-rename to change the extension .pipe(rename({ extname: '.min.js' })) .pipe(dest('output/')); }
固然,除了插件,咱們也可使用其餘庫:
const del = require('delete'); exports.default = function(cb) { // Use the `delete` module directly, instead of using gulp-rimraf del(['output/*.js'], cb); }
最後也能夠藉助through2插件使用內聯方式自行處理,也能夠利用次through2進行gulp插件開發:
const { src, dest } = require('gulp'); const uglify = require('uglify-js'); const through2 = require('through2'); exports.default = function() { return src('src/*.js') // Instead of using gulp-uglify, you can create an inline plugin .pipe(through2.obj(function(file, _, cb) { if (file.isBuffer()) { const code = uglify.minify(file.contents.toString()) file.contents = Buffer.from(code) } cb(null, file); })) .pipe(dest('output/')); }
咱們可使用watch方法來監聽文件的改動,以便在改動時執行相應的處理任務。
const { watch, series } = require('gulp'); function clean(cb) { // body omitted cb(); } function javascript(cb) { // body omitted cb(); } function css(cb) { // body omitted cb(); } exports.default = function() { watch('src/*.css', css); watch('src/*.js', series(clean, javascript)); };
src(globs, [options])
:輸入globs[string|array]
: 要處理文件的路徑匹配規則options
:配置項,點擊查看詳情 const { src, dest } = require('gulp'); function copy() { return src('input/*.js', { sourcemaps: true }) .pipe(dest('output/')); }
dest(directory, [options])
:輸出directory[string|function]
: 輸出的路徑options
:配置項,點擊查看詳情 const { src, dest } = require('gulp'); const uglify = require('gulp-uglify'); src('input/**/*.js', { sourcemaps: true }) .pipe(uglify()) .pipe(dest('output/', { sourcemaps: '.' }));
series(...tasks)
:順序執行多個任務tasks[function|string]
:任務名或者functionconst { series } = require('gulp'); function javascript(cb) { // body omitted cb(); } function css(cb) { // body omitted cb(); } exports.build = series(javascript, css);
parallel(...tasks)
:多個任務同時執行tasks[function|string]
:任務名或者functionconst { parallel } = require('gulp'); function javascript(cb) { // body omitted cb(); } function css(cb) { // body omitted cb(); } exports.build = parallel(javascript, css);
watch(globs, [options], [task])
:文件監聽globs[string|array]
: 要監聽的文件options
:配置項,點擊查看詳情 task[function|string]
:要執行的任務或操做const { watch } = require('gulp'); watch(['input/*.js', '!input/something.js'], function(cb) { // body omitted cb(); });
監聽方法會返回一共實例,該實例提供了以下幾個方法:
watcher.on(eventName, eventHandler)
eventName[string]
:事件名稱,能夠是add
, addDir
, change
, unlink
, unlinkDir
, ready
, error
, or all
eventHandler[function]
:事件處理函數,該函數接收path和stats兩個參數。const { watch } = require('gulp'); const watcher = watch(['input/*.js']); watcher.on('change', function(path, stats) { console.log(`File ${path} was changed`); }); watcher.on('add', function(path, stats) { console.log(`File ${path} was added`); }); watcher.on('unlink', function(path, stats) { console.log(`File ${path} was removed`); }); watcher.close();
watcher.close()
:關閉文件監聽器watcher.add(globs)
:添加文件到監聽器globs[string|array]
: 要添加的文件watcher.unwatch(globs)
:移除監聽器中的文件globs[string|array]
: 要移除的文件task([taskName], taskFunction)
:定義任務(4.0推薦使用function替代此方法)taskName[string]
:任務名稱taskFunction[function]
:處理函數const { task } = require('gulp'); task('build', function(cb) { // body omitted cb(); }); const build = task('build');
lastRun(task, [precision])
:獲取任務最後運行完成的時間戳task[function|string]
:指定獲取的任務precision[number]
:精度,默認1000可以使用此方法進行增量編譯。
const { src, dest, lastRun, watch } = require('gulp'); const imagemin = require('gulp-imagemin'); function images() { return src('src/images/**/*.jpg', { since: lastRun(images) }) .pipe(imagemin()) .pipe(dest('build/img/')); } exports.default = function() { watch('src/images/**/*.jpg', images); };
tree([options])
:獲取任務依賴關係options[object]
:deep默認爲false,只會返回頂級任務,若是爲true,則會返回整個任務樹。gulp.tree({ deep: true })
Vinyl
:一個文件描述器,本身開發插件可能會用到具體的用法見gulp源碼解析(二)—— vinyl-fs
我經常使用的api就這些,其餘的api能夠自行查看官方文檔。
若是要查找gulp插件,通常有兩個地方:
總結:
gulp自己其實很是簡單,提供的api不多,可是簡潔夠用。在瞭解這些api後,你可能以爲最複雜的仍是瞭解各插件的用法。
其實,構建工具(gulp、webpack之類)自己都是相對較簡單的,這纔是它們該有的樣子,自己就很複雜了,我才懶得用。可是在使用過程當中,我以爲有兩個難點:
最後,本人才疏學淺,有不妥之處,歡迎指正。