Gulp簡介
最近流行前端構建工具,苦于之前使用Grunt,代碼很難閱讀,現在出了Gulp,真是擺脫了痛苦。發現了一篇很好的Gulp英文教程,整理翻譯給大家看看。
為什么使用Gulp
Gulp基于Node.js的前端構建工具,通過Gulp的插件可以實現前端代碼的編譯(sass、less)、壓縮、測試;圖片的壓縮;瀏覽器自動刷新,還有許多強大的插件可以在這里查找。比起Grunt不僅配置簡單而且更容易閱讀和維護,我們可以做一個對比:
Grunt:
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
'dist/assets/css/main.css': 'src/styles/main.scss',
}
}
},
autoprefixer: {
dist: {
options: {
browsers: [
'last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'
]
},
src: 'dist/assets/css/main.css',
dest: 'dist/assets/css/main.css'
}
},
grunt.registerTask('styles', ['sass', 'autoprefixer']);
在Grunt里面,每個插件使用的方式相對獨立,正如上面的代碼通過sass插件將main.sass文件編譯成main.css文件,接著autoprefixer插件再對編譯好的main.css文件進行修改,最后覆蓋main.css。那么覆蓋文件就是多余的了,有沒辦法做到sass和autoprefixer一并處理完再生成main.css?我們來看看Gulp是如何做到的:
Gulp:
gulp.task('sass', function() {
return gulp.src('src/styles/main.scss')
.pipe(sass({ style: 'compressed' }))
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(gulp.dest('dist/assets/css'))
});
使用Gulp我們只需要放一個路徑,通過管道方式使用插件,最后生成文件,是不是有種jQuery的感覺。這種方式不僅提高效率而且一眼就看清了輸入文件和輸出文件,再也不用看gruntfile看得眼花繚亂了。
再打個比喻,Grunt的插件就像獨立的工廠,這個工廠生成出來的產品打包封裝好后再送到另一個工廠去加工,使用了Gulp后實現了工廠的合并,所有東西都在一個工廠里完成了。現在是否對Gulp感興趣了,那就開始使用Gulp吧!
安裝
首先我們要全局安裝一遍:
$ npm install gulp -g
接著我們要進去到項目的根目錄再安裝一遍(確保你根目錄存在package.json文件):
$ npm install gulp --save-dev
—save-dev這個屬性會將條目保存到你package.json的devDependencies里面
安裝Gulp插件
我們將要使用Gulp插件來完成我們以下任務:
- sass的編譯(gulp-ruby-sass)
- 自動添加css前綴(gulp-autoprefixer)
- 壓縮css(gulp-minify-css)
- js代碼校驗(gulp-jshint)
- 合并js文件(gulp-concat)
- 壓縮js代碼(gulp-uglify)
- 壓縮圖片(gulp-imagemin)
- 自動刷新頁面(gulp-livereload)
- 圖片緩存,只有圖片替換了才壓縮(gulp-cache)
- 更改提醒(gulp-notify)
- 清除文件(del)
安裝這些插件需要運行如下命令:
$ npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache del --save-dev
上面是一些常用的插件,如果想要找更多的插件點擊這里
加載插件
接著我們要創建一個gulpfile.js在根目錄下,然后在里面加載插件:
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
livereload = require('gulp-livereload'),
del = require('del');
Gulp的插件和Grunt有些許不一樣,Grunt插件是為了更好的完成一項任務。就像Grunt的imagemin插件就利用了緩存來避免重復壓縮,而Gulp要利用gulp-cache來完成,當然啦,不僅限定于緩存圖片。
建立任務
編譯sass、自動添加css前綴和壓縮
首先我們編譯sass,添加前綴,保存到我們指定的目錄下面,還沒結束,我們還要壓縮,給文件添加.min后綴再輸出壓縮文件到指定目錄,最后提醒任務完成了:
gulp.task('styles', function() {
return gulp.src('src/styles/main.scss')
.pipe(sass({ style: 'expanded' }))
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(gulp.dest('dist/assets/css'))
.pipe(rename({suffix: '.min'}))
.pipe(minifycss())
.pipe(gulp.dest('dist/assets/css'))
.pipe(notify({ message: 'Styles task complete' }));
});
讓我解釋一下:
gulp.task('styles', function () {...});
gulp.task這個API用來創建任務,在命令行下可以輸入$ gulp styles來執行上面的任務。
return gulp.src('src/styles/main.scss')
gulp.src這個API設置需要處理的文件的路徑,可以是多個文件以數組的形式[main.scss, vender.scss],也可以是正則表達式/*/.scss。
.pipe(sass({ style: 'expanded' }))
我們使用.pipe()這個API將需要處理的文件導向sass插件,那些插件的用法可以在github上找到,為了方便大家查找我已經在上面列出來了。
.pipe(gulp.dest('dist/assets/css'));
gulp.dest()API設置生成文件的路徑,一個任務可以有多個生成路徑,一個可以輸出未壓縮的版本,另一個可以輸出壓縮后的版本。
為了更好的了解Gulp API,強烈建議看一下Gulp API文檔,其實Gulp API就這么幾個,沒什么好可怕的。
js代碼校驗、合并和壓縮
希望大家已經知道如何去創建一個任務了,接下來我們完成scripts的校驗、合并和壓縮的任務吧:
gulp.task('scripts', function() {
return gulp.src('src/scripts/**/*.js')
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(concat('main.js'))
.pipe(gulp.dest('dist/assets/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('dist/assets/js'))
.pipe(notify({ message: 'Scripts task complete' }));
});
需要提醒的是我們要設置JSHint的reporter方式,上面使用的是default默認的,了解更多點擊這里。
壓縮圖片
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' }));
});
這個任務使用imagemin插件把所有在src/images/目錄以及其子目錄下的所有圖片(文件)進行壓縮,我們可以進一步優化,利用緩存保存已經壓縮過的圖片,使用之前裝過的gulp-cache插件,不過要修改一下上面的代碼:
將這行代碼:
.pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
修改成:
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
現在,只有新建或者修改過的圖片才會被壓縮了。
清除文件
在任務執行前,最好先清除之前生成的文件:
gulp.task('clean', function(cb) {
del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img'], cb)
});
在這里沒有必要使用Gulp插件了,可以使用NPM提供的插件。我們用一個回調函數(cb)確保在退出前完成任務。
設置默認任務(default)
我們在命令行下輸入$ gulp執行的就是默認任務,現在我們為默認任務指定執行上面寫好的三個任務:
gulp.task('default', ['clean'], function() {
gulp.start('styles', 'scripts', 'images');
});
在這個例子里面,clean任務執行完成了才會去運行其他的任務,在gulp.start()里的任務執行的順序是不確定的,所以將要在它們之前執行的任務寫在數組里面。
監聽文件
為了監聽文件的是否修改以便執行相應的任務,我們需要創建一個新的任務,然后利用gulp.watchAPI實現:
gulp.task('watch', function() {
// Watch .scss files
gulp.watch('src/styles/**/*.scss', ['styles']);
// Watch .js files
gulp.watch('src/scripts/**/*.js', ['scripts']);
// Watch image files
gulp.watch('src/images/**/*', ['images']);
});
我們將不同類型的文件分開處理,執行對應的數組里的任務。現在我們可以在命令行輸入$ gulp watch執行監聽任務,當.sass、.js和圖片修改時將執行對應的任務。
自動刷新頁面
Gulp也可以實現當文件修改時自動刷新頁面,我們要修改watch任務,配置LiveReload:
gulp.task('watch', function() {
// Create LiveReload server
livereload.listen();
// Watch any files in dist/, reload on change
gulp.watch(['dist/**']).on('change', livereload.changed);
});
要使這個能夠工作,還需要在瀏覽器上安裝LiveReload插件,除此之外還能這樣做
所有
/*!
* gulp
* $ npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache del --save-dev
*/
// Load plugins
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
livereload = require('gulp-livereload'),
del = require('del');
// Styles
gulp.task('styles', function() {
return gulp.src('src/styles/main.scss')
.pipe(sass({ style: 'expanded', }))
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(gulp.dest('dist/styles'))
.pipe(rename({ suffix: '.min' }))
.pipe(minifycss())
.pipe(gulp.dest('dist/styles'))
.pipe(notify({ message: 'Styles task complete' }));
});
// Scripts
gulp.task('scripts', function() {
return gulp.src('src/scripts/**/*.js')
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(concat('main.js'))
.pipe(gulp.dest('dist/scripts'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('dist/scripts'))
.pipe(notify({ message: 'Scripts task complete' }));
});
// Images
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest('dist/images'))
.pipe(notify({ message: 'Images task complete' }));
});
// Clean
gulp.task('clean', function(cb) {
del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img'], cb)
});
// Default task
gulp.task('default', ['clean'], function() {
gulp.start('styles', 'scripts', 'images');
});
// Watch
gulp.task('watch', function() {
// Watch .scss files
gulp.watch('src/styles/**/*.scss', ['styles']);
// Watch .js files
gulp.watch('src/scripts/**/*.js', ['scripts']);
// Watch image files
gulp.watch('src/images/**/*', ['images']);
// Create LiveReload server
livereload.listen();
// Watch any files in dist/, reload on change
gulp.watch(['dist/**']).on('change', livereload.changed);
});
在gist上有源碼,并且附上Grunt的實現作為對比。
參考鏈接:http://markgoodyear.com/2014/01/getting-started-with-gulp/
http://markpop.github.io/2014/09/17/Gulp%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/