原文:http://ju.outofmemory.cn/entry/103253javascript
Gulp是一個構建工具, 功能相似grunt, 以及Java生態圈的ant, maven, gradle等。 其它的javascript生態圈的構建工具能夠參考: List of JavaScript Build Tools
它採用了一種流式處理的方式, 編寫起來簡單直觀。 相對於其它javascript構建工具, 母親啊它的star數是僅次於grunt,流行度仍是比較高的。
經過」代碼優於配置」 (code over configuration), 經過javascript編寫構建任務, 充分利用javascript生態圈的組件, 能夠實現簡單靈活的任務管理。 經過node stream的方式,直接在內存中管道式處理流,沒必要緩存到硬盤上, 節省構建時間。css
Gulp介紹請參考我轉載的另外一篇文章: Building With Gulp
另外有一篇很好的入門文章: Getting started with gulp, 繁體版, 簡體中文硬翻版html
從個人實踐上來看, gulp要比grunt更好的管理構建過程。 編寫簡單,條理清晰,功能強大,學習無曲線。前端
Gulp是基於Node.js構建的,所以Gulp源文件和你用來定義任務的Gulp文件都被寫進了JavaScript(或者CoffeeScript)裏。 Gulp自己雖然不能完成不少任務,但它有大量插件可用,開發者能夠訪問插件頁面或者在npm搜索gulpplugin或者gulpfriendly就能看到。例如,有些插件能夠用來執行JSHint、編譯CoffeeScript,執行Mocha測試,甚至更新版本號。如今有大約980個左右的插件可使用。你能夠到http://gulpjs.com/plugins/或者http://npmsearch.com/?q=keywords:gulpplugin查找所需的軟件。
面對如此衆多的插件, 想要所有了解並靈活運用它們幾乎是不可能的事情。 實際開發中多參考別的項目的實現, 根據本身的需求尋找合適的插件, 總結並開發本身的插件, 逐步積累對gulp的認識。java
本文列出經常使用的幾個插件, 並在未來的開發中更新此文做爲記錄文檔。 多個插件和grunt的插件功能相似。node
首先介紹如下gulp自己的API, 至關的簡潔,只有幾個函數。python
gulp API
流(Stream)可以經過一系列的小函數來傳遞數據,這些函數會對數據進行修改,而後把修改後的數據傳遞給下一個函數。
看一個簡單例子:mysql
var gulp =require('gulp'), uglify =require('gulp-uglify'); gulp.task('minify',function(){ gulp.src('js/app.js').pipe(uglify()).pipe(gulp.dest('build'))});
gulp.src()函數用字符串匹配一個文件或者文件的編號(被稱爲「glob」),而後建立一個對象流來表明這些文件,接着傳遞給uglify()函數,它接受文件對象以後返回有新壓縮源文件的文件對象,最後那些輸出的文件被輸入gulp.dest()函數,並保存下來。linux
想了解更多的關於node stream方面的知識,能夠訪問stream-handbook。 stream-handbook中文翻譯git
gulp.src(globs[, options])
根據globs提供的文件列表, 獲得一個Vinyl文件的stream, 能夠按照管道模式給其它插件處理。
gulp.src('client/templates/*.jade').pipe(jade()).pipe(minify()).pipe(gulp.dest('build/minified_templates'));
gulp.dest(path[, options])
將管道中的數據寫入到文件夾。
gulp.task(name[, deps], fn)
使用orchestrator定義任務。
gulp.task('somename',function(){// Do stuff});
deps 是任務數組,在執行本任務時數組中的任務要執行並完成。
gulp.watch(glob [, opts], tasks), gulp.watch(glob [, opts, cb])
監控文件。當監控的文件有所改變時執行特定的任務。
Recipes
下面的文章總結的幾個常見問題的解決方案,很是有參考價值。
https://github.com/gulpjs/gulp/tree/master/docs/recipes#recipes
gulp-browserify
browserify能夠爲瀏覽器編譯node風格的遵循commonjs的模塊。 它搜索文件中的require()
調用, 遞歸的創建模塊依賴圖。
var gulp =require('gulp');var browserify =require('gulp-browserify');// Basic usage gulp.task('scripts',function(){// Single entry point to browserify gulp.src('src/js/app.js').pipe(browserify({ insertGlobals :true, debug :!gulp.env.production })).pipe(gulp.dest('./build/js'))});
gulp-jshint
gulp的jshint插件。
jshint是一個偵測javascript代碼中錯誤和潛在問題的工具。
用法:
var jshint =require('gulp-jshint');var gulp =require('gulp'); gulp.task('lint',function(){return gulp.src('./lib/*.js').pipe(jshint()).pipe(jshint.reporter('YOUR_REPORTER_HERE'));});
gulp-jslint
jslint是一個javascript代碼質量檢測工具。
gulp-jslint是它的gulp插件。
var gulp =require('gulp');var jslint =require('gulp-jslint');// build the main source into the min file gulp.task('default',function(){return gulp.src(['source.js'])// pass your directives// as an object.pipe(jslint({// these directives can// be found in the official// JSLint documentation. node:true, evil:true, nomen:true,// you can also set global// declarations for all source// files like so:global:[], predef:[],// both ways will achieve the// same result; predef will be// given priority because it is// promoted by JSLint// pass in your prefered// reporter like so: reporter:'default',// ^ there's no need to tell gulp-jslint// to use the default reporter. If there is// no reporter specified, gulp-jslint will use// its own.// specify whether or not// to show 'PASS' messages// for built-in reporter errorsOnly:false}))// error handling:// to handle on error, simply// bind yourself to the error event// of the stream, and use the only// argument as the error object// (error instanceof Error).on('error',function(error){ console.error(String(error));});});
imagemin
imagemin是壓縮圖片的工具。
var gulp =require('gulp');var imagemin =require('gulp-imagemin');var pngquant =require('imagemin-pngquant'); gulp.task('default',function(){return gulp.src('src/images/*').pipe(imagemin({ progressive:true, svgoPlugins:[{removeViewBox:false}],use:[pngquant()]})).pipe(gulp.dest('dist'));});
glup-sass
sass是編寫css的一套語法。 使用它的預處理器能夠將sass語法的css處理成css格式。
glup-sass語法:
var gulp =require('gulp');var sass =require('gulp-sass'); gulp.task('sass',function(){ gulp.src('./scss/*.scss').pipe(sass()).pipe(gulp.dest('./css'));});
gulp-ruby-sass是另一款sass的gulp插件, 比glup-sass慢,可是更穩定,功能更多。 它使用compass預處理sass文件,因此你須要安裝ruby和compass。
var gulp =require('gulp');var sass =require('gulp-ruby-sass'); gulp.task('default',function(){return gulp.src('src/scss/app.scss').pipe(sass({sourcemap:true, sourcemapPath:'../scss'})).on('error',function(err){ console.log(err.message);}).pipe(gulp.dest('dist/css'));});
browser-sync
BrowserSync 是一個自動化測試輔助工具,能夠幫你在網頁文件變動時自動載入新的網頁。
用法:
var gulp = require('gulp');
var browserSync =require('browser-sync');// Static server gulp.task('browser-sync',function(){ browserSync({ server:{ baseDir:"./"}});});// or... gulp.task('browser-sync',function(){ browserSync({ proxy:"yourlocal.dev"});});
還可使用proxy-middleware
做爲http proxy,轉發特定的請求。
gulp-handlebars
handlebars是一個模版引擎庫, ember.js用它做爲前端的模版引擎。
gulp-handlebars編譯handlebars文件。
用法:
var handlebars =require('gulp-handlebars');var wrap =require('gulp-wrap');var declare =require('gulp-declare');var concat =require('gulp-concat'); gulp.task('templates',function(){ gulp.src('source/templates/*.hbs').pipe(handlebars()).pipe(wrap('Handlebars.template(<%= contents %>)')).pipe(declare({namespace:'MyApp.templates', noRedeclare:true,// Avoid duplicate declarations})).pipe(concat('templates.js')).pipe(gulp.dest('build/js/'));});
gulp-usemin
用來將HTML 文件中(或者templates/views)中沒有優化的script 和stylesheets 替換爲優化過的版本。
usemin 暴露兩個內置的任務,分別爲:
- useminPrepare 爲將指定文件中的 usemin block 轉換爲單獨的一行(優化版本)準備配置。這經過爲每一個優化步驟生成名爲 generated 的子任務來完成。
- usemin 使用優化版本替換 usemin 塊,若是在磁盤上能夠找到 revisioned 版本,則替換爲 revisioned 版本。
usemin塊以下定義:
<!-- build:<pipelineId>(alternate search path) <path> --> ... HTML Markup, list of script / link tags. <!-- endbuild -->
如
<!-- build:css style.css --><linkrel="stylesheet"href="http://colobu.com/2014/11/17/gulp-plugins-introduction/css/clear.css"/><linkrel="stylesheet"href="http://colobu.com/2014/11/17/gulp-plugins-introduction/css/main.css"/><!-- endbuild --><!-- build:js js/lib.js --><scriptsrc="http://colobu.com/2014/11/17/lib/angular-min.js"></script><scriptsrc="http://colobu.com/2014/11/17/lib/angular-animate-min.js"></script><!-- endbuild --><!-- build:js1 js/app.js --><scriptsrc="http://colobu.com/2014/11/17/gulp-plugins-introduction/js/app.js"></script><scriptsrc="http://colobu.com/2014/11/17/gulp-plugins-introduction/js/controllers/thing-controller.js"></script><scriptsrc="http://colobu.com/2014/11/17/gulp-plugins-introduction/js/models/thing-model.js"></script><scriptsrc="http://colobu.com/2014/11/17/gulp-plugins-introduction/js/views/thing-view.js"></script><!-- endbuild --><!-- build:remove --><scriptsrc="http://colobu.com/2014/11/17/gulp-plugins-introduction/js/localhostDependencies.js"></script><!-- endbuild -->
gulp-usemin用法以下:
var usemin =require('gulp-usemin');var uglify =require('gulp-uglify');var minifyHtml =require('gulp-minify-html');var minifyCss =require('gulp-minify-css');var rev =require('gulp-rev'); gulp.task('usemin',function(){ gulp.src('./*.html').pipe(usemin({ css:[minifyCss(),'concat'], html:[minifyHtml({empty:true})], js:[uglify(), rev()]})).pipe(gulp.dest('build/'));});
gulp-uglify
uglify是一款javascript代碼優化工具,能夠解析,壓縮和美化javascript。
用法:
var uglify =require('gulp-uglify'); gulp.task('compress',function(){ gulp.src('lib/*.js').pipe(uglify()).pipe(gulp.dest('dist'))});
gulp-sourcemaps
在現代javascript開發中, JavaScript腳本正變得愈來愈複雜。大部分源碼(尤爲是各類函數庫和框架)都要通過轉換,才能投入生產環境。
常見的轉換狀況:
- 壓縮,減少體積。
- 多個文件合併,減小HTTP請求數。
- 其餘語言編譯成JavaScript。最多見的例子就是CoffeeScript。
這三種狀況,都使得實際運行的代碼不一樣於開發代碼,除錯(debug)變得困難重重。
Source map就是一個信息文件,裏面儲存着位置信息。也就是說,轉換後的代碼的每個位置,所對應的轉換前的位置。有了它,出錯的時候,除錯工具將直接顯示原始代碼,而不是轉換後的代碼。
var gulp =require('gulp');var plugin1 =require('gulp-plugin1');var plugin2 =require('gulp-plugin2');var sourcemaps =require('gulp-sourcemaps'); gulp.task('javascript',function(){ gulp.src('src/**/*.js').pipe(sourcemaps.init()).pipe(plugin1()).pipe(plugin2()).pipe(sourcemaps.write()).pipe(gulp.dest('dist'));});
其它一些關注度高的gulp插件
gulp-inject
能夠注入css,javascript和web組件,不需手工更新ndex.html。
<!DOCTYPE html><html><head><title>My index</title><!-- inject:css --><!-- endinject --></head><body><!-- inject:js --><!-- endinject --></body></html>
var gulp =require('gulp');var inject =require("gulp-inject"); gulp.task('index',function(){var target = gulp.src('./src/index.html');// It's not necessary to read the files (will speed up things), we're only after their paths:var sources = gulp.src(['./src/**/*.js','./src/**/*.css'],{read:false});return target.pipe(inject(sources)).pipe(gulp.dest('./src'));});
gulp-header
爲管道中的文件增長header。
var header =require('gulp-header'); gulp.src('./foo/*.js').pipe(header('Hello')).pipe(gulp.dest('./dist/') gulp.src('./foo/*.js').pipe(header('Hello <%= name %>\n',{ name :'World'})).pipe(gulp.dest('./dist/') gulp.src('./foo/*.js').pipe(header('Hello ${name}\n',{ name :'World'})).pipe(gulp.dest('./dist/')//var pkg =require('./package.json');var banner =['/**',' * <%= pkg.name %> - <%= pkg.description %>',' * @version v<%= pkg.version %>',' * @link <%= pkg.homepage %>',' * @license <%= pkg.license %>',' */',''].join('\n'); gulp.src('./foo/*.js').pipe(header(banner,{ pkg : pkg })).pipe(gulp.dest('./dist/')
相應的還有一個gulp-footer
插件。
gulp-filter
篩選vinyl stream中的文件。
var gulp =require('gulp');var jscs =require('gulp-jscs');var gulpFilter =require('gulp-filter'); gulp.task('default',function(){// create filter instance inside task functionvar filter = gulpFilter(['*','!src/vendor']);return gulp.src('src/*.js')// filter a subset of the files.pipe(filter)// run them through a plugin.pipe(jscs())// bring back the previously filtered out files (optional).pipe(filter.restore()).pipe(gulp.dest('dist'));});
gulp-changed
只容許改變的文件經過管道。
var gulp =require('gulp');var changed =require('gulp-changed');var ngmin =require('gulp-ngmin');// just as an examplevar SRC ='src/*.js';var DEST ='dist'; gulp.task('default',function(){return gulp.src(SRC).pipe(changed(DEST))// ngmin will only get the files that// changed since the last time it was run.pipe(ngmin()).pipe(gulp.dest(DEST));});
gulp-bower
執行bower安裝。
var gulp =require('gulp');var bower =require('gulp-bower'); gulp.task('bower',function(){return bower().pipe(gulp.dest('lib/'))});
gulp-if
有條件的執行任務
gulp-replace
字符串替換插件。
var replace =require('gulp-replace'); gulp.task('templates',function(){ gulp.src(['file.txt']).pipe(replace(/foo(.{3})/g,'$1foo')).pipe(gulp.dest('build/file.txt'));});
gulp-shell
能夠執行shell命令
gulp-exec
exec插件
gulp-install
安裝npm和bower包, 若是它們的配置文件存在的話。
var install =require("gulp-install"); gulp.src(__dirname +'/templates/**').pipe(gulp.dest('./')).pipe(install());
gulp-rename
改變管道中的文件名。
var rename =require("gulp-rename");// rename via string gulp.src("./src/main/text/hello.txt").pipe(rename("main/text/ciao/goodbye.md")).pipe(gulp.dest("./dist"));// ./dist/main/text/ciao/goodbye.md// rename via function gulp.src("./src/**/hello.txt").pipe(rename(function(path){ path.dirname +="/ciao"; path.basename +="-goodbye"; path.extname =".md"})).pipe(gulp.dest("./dist"));// ./dist/main/text/ciao/hello-goodbye.md// rename via hash gulp.src("./src/main/text/hello.txt",{base: process.cwd()}).pipe(rename({ dirname:"main/text/ciao", basename:"aloha", prefix:"bonjour-", suffix:"-hola", extname:".md"})).pipe(gulp.dest("./dist"));// ./dist/main/text/ciao/bonjour-aloha-hola.md
gulp-ignore
忽略管道中的部分文件。
gulp-util
提供一些輔助方法。
gulp-clean
提供clean功能。
var gulp =require('gulp');var clean =require('gulp-clean'); gulp.task('clean',function(){return gulp.src('build',{read:false}).pipe(clean());});
gulp-concat
鏈接合併文件。
var concat =require('gulp-concat'); gulp.task('scripts',function(){ gulp.src('./lib/*.js').pipe(concat('all.js')).pipe(gulp.dest('./dist/'))});
gulp-wrap
將一個lodash模版包裝成流內容。
gulp-declare
安全的聲明命名空間,設置屬性。
var declare =require('gulp-declare');var concat =require('gulp-concat'); gulp.task('models',function(){// Define each model as a property of a namespace according to its filename gulp.src(['client/models/*.js']).pipe(declare({namespace:'MyApp.models', noRedeclare:true// Avoid duplicate declarations})).pipe(concat('models.js'))// Combine into a single file.pipe(gulp.dest('build/js/'));});
更多的文章
Gulp是一個構建工具, 功能相似grunt, 以及Java生態圈的ant, maven, gradle等。 其它的javascript生態圈的構建工具能夠參考: List of JavaScript Build Tools
它採用了一種流式處理的方式, 編寫起來簡單直觀。 相對於其它javascript構建工具, 母親啊它的star數是僅次於grunt,流行度仍是比較高的。
經過」代碼優於配置」 (code over configuration), 經過javascript編寫構建任務, 充分利用javascript生態圈的組件, 能夠實現簡單靈活的任務管理。 經過node stream的方式,直接在內存中管道式處理流,沒必要緩存到硬盤上, 節省構建時間。
Gulp介紹請參考我轉載的另外一篇文章: Building With Gulp
另外有一篇很好的入門文章: Getting started with gulp, 繁體版, 簡體中文硬翻版
從個人實踐上來看, gulp要比grunt更好的管理構建過程。 編寫簡單,條理清晰,功能強大,學習無曲線。
Gulp是基於Node.js構建的,所以Gulp源文件和你用來定義任務的Gulp文件都被寫進了JavaScript(或者CoffeeScript)裏。 Gulp自己雖然不能完成不少任務,但它有大量插件可用,開發者能夠訪問插件頁面或者在npm搜索gulpplugin或者gulpfriendly就能看到。例如,有些插件能夠用來執行JSHint、編譯CoffeeScript,執行Mocha測試,甚至更新版本號。如今有大約980個左右的插件可使用。你能夠到http://gulpjs.com/plugins/或者http://npmsearch.com/?q=keywords:gulpplugin查找所需的軟件。
面對如此衆多的插件, 想要所有了解並靈活運用它們幾乎是不可能的事情。 實際開發中多參考別的項目的實現, 根據本身的需求尋找合適的插件, 總結並開發本身的插件, 逐步積累對gulp的認識。
本文列出經常使用的幾個插件, 並在未來的開發中更新此文做爲記錄文檔。 多個插件和grunt的插件功能相似。