Gulp使用node.js流,由于它不需要将临时文件/文件夹写入磁盘,构建起来速度更快。Gulp允许你输入你的源文件,通过一堆插件管理它们,并在最后得到一个输出,而Grunt则为每一个插件配置一个输入和输出。下面我们先看看Grunt和Gulp的一个基本使用Sass构建的样子:
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插件,然后保存输出。 然后我们需要配置Autoprefixer来输入Sass的输出,然后输出另一个文件。 让我们来看看与gulp相同的配置:
Gulp:
gulp.task('sass', function() {
return sass('src/styles/main.scss', { 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'))
});
我们只用输入一个文件,它被Sass插件修改后,传递给Autoprefixer插件并修改,然后我们得到一个文件。这个构建过程更快,因为我们没有读取和写入不必要的文件。
下面我们创建一个基本的gulp文件,其中包含一些核心任务。
$ npm install gulp -g
或者
// 进到你的项目文件比如gulp-demo
// cd gulp-demo
$ npm install gulp --save-dev
这会将gulp本地安装到项目中,并将其保存到package.json文件中的devDependencies。
安装gulp插件
- 编译Sass文件 (gulp-ruby-sass)
- 根据设置浏览器版本自动处理浏览器前缀 (gulp-autoprefixer)
- 压缩CSS (gulp-cssnano)
- 语法检查工具 (gulp-jshint)
- 合并文件 (gulp-concat)
- 压缩JS (gulp-uglify)
- 压缩图片 (gulp-imagemin)
- 自动刷新 (gulp-connect)
- 缓存图片,仅压缩被更改的图片 (gulp-cache)
- 通知变化 (gulp-notify)
- 编译前清理文件 (del)
$ npm install gulp-ruby-sass gulp-autoprefixer gulp-cssnano gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-connect gulp-cache del --save-dev
加载插件
首先,创建一个gulpfile.js文件
touch gulpfile.js
然后添加以下内容
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
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'),
del = require('del'),
connect = require('gulp-connect');//livereload
Gulp插件与Grunt插件略有不同 - 它们被设计用来完成一件事,一件事。比如Grunt的imagemin使用缓存来避免重新压缩已经被压缩的图像。而Gulp可以用一个缓存插件完成,也可以用来缓存其他的东西。 这为构建过程增加了额外的灵活性。
我们可以像Grunt一样自动加载所有安装的插件,但为了本文的目的,我们将坚持手动方法。
创建任务
实时更新
gulp.task('connect', function () {
connect.server({
livereload: true
});
});
编译Sass,自动处理前缀,压缩CSS
gulp.task('styles', function() {
return sass('src/styles/main.scss', { style: 'expanded' })
.pipe(autoprefixer('last 2 version'))
.pipe(gulp.dest('dist/assets/css'))
.pipe(rename({suffix: '.min'}))
.pipe(cssnano())
.pipe(gulp.dest('dist/assets/css'))
.pipe(notify({ message: 'Styles task complete' }))
.pipe(connect.reload())
});
这里先稍作解释
gulp.task('styles', function() { ... )};
gulp.task这是用来创建任务的API。 你可以在终端单独执行命令$ gulp styles
return sass('src/styles/main.scss', { style: 'expanded' })
这是我们定义源文件并传递任何选项的新gulp-ruby-sass API。对于许多其他的插件,你可以使用我们稍后在这篇文章中使用的gulp.src API(return gulp.src(...))。它也可以是glob模式,比如/*/.scss来匹配多个文件。 通过返回流使它异步,确保任务完全完成,然后我们收到通知说完成。
.pipe(autoprefixer('last 2 version'))
我们使用.pipe()将源文件传送到插件中。
.pipe(gulp.dest('dist/assets/css'));
gulp.dest API是我们设置目标路径的地方。一个任务可以有多个目标,一个输出扩展版本,另一个输出minifed版本。 这在上面的样式任务中得到了证明。
校验语法, 合并文件, 压缩JS
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' }))
.pipe(connect.reload())
});
这里我们使用gulp.src API来指定我们的输入文件。
定义Html任务
gulp.task('html', function () {
return gulp.src('src/*.html')
.pipe(gulp.dest('dist'))
.pipe(connect.reload());
});
压缩图片
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' }))
.pipe(connect.reload())
});
清理
在部署之前,清理目标文件夹并重建文件是一个好习惯 - 可以防止源文件中已经删除的留在目标文件夹中:
gulp.task('clean', function() {
return del(['dist/styles', 'dist/scripts', 'dist/images', 'dist/html']);
});
我们不需要在这里使用gulp插件,因为我们可以直接在gulp中利用Node模块。我们使用return来确保任务在退出之前完成。
监控
要监控我们的文件并在更改时执行必要的任务,我们首先需要创建一个新任务,然后使用gulp.watch API开始监控文件:
gulp.task('watch', function() {
// 监控 .scss 文件
gulp.watch('src/styles/**/*.scss', ['styles']);
// 监控 .js 文件
gulp.watch('src/scripts/**/*.js', ['scripts']);
// 监控图片文件
gulp.watch('src/images/**/*', ['images']);
// 监控 .html文件
gulp.watch('src/*.html', ['html']);
});
我们通过gulp.watch API指定要观看的文件,并通过依赖数组定义要运行的任务。我们现在可以运行$ gulp watch
,任何对.scss,.js或图像文件的更改都将运行它们各自的任务。
默认任务
我们可以创建一个默认任务,使用$ gulp
运行,运行我们创建的所有三个任务:
gulp.task('default', ['clean'], function() {
gulp.start('styles', 'scripts', 'html', 'images', 'watch', 'connect');
});
注意gulp.task中的附加数组。这是我们可以定义任务依赖关系的地方。在这个例子中,clean任务将在gulp.start中的任务之前运行。
注意:建议不要使用gulp.start来执行依赖项arrary中的任务,但是在这种情况下为了确保clean完全完成,这似乎是最好的选择。
最终gulpfile.js文件
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
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'),
del = require('del'),
connect = require('gulp-connect');//livereload
// Styles
gulp.task('styles', function () {
return sass('src/styles/main.scss', { style: 'expanded' })
.pipe(autoprefixer('last 2 version'))
.pipe(gulp.dest('dist/styles'))
.pipe(rename({ suffix: '.min' }))
.pipe(cssnano())
.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' }))
.pipe(connect.reload())
});
// Html
gulp.task('html', function () {
return gulp.src('src/*.html')
.pipe(gulp.dest('dist'))
.pipe(connect.reload());
});
// 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' }))
.pipe(connect.reload())
});
// Clean
gulp.task('clean', function () {
return del(['dist/styles', 'dist/scripts', 'dist/images', 'dist/html']);
});
// Default task
gulp.task('default', ['clean'], function () {
gulp.start('styles', 'scripts', 'html', 'images', 'watch', 'connect');
});
// Livereload
gulp.task('connect', function () {
connect.server({
livereload: true
});
});
// Watch
gulp.task('watch', function () {
gulp.watch('src/styles/**/*.scss', ['styles']);
gulp.watch('src/scripts/**/*.js', ['scripts']);
gulp.watch('src/images/**/*', ['images']);
gulp.watch('src/*.html', ['html']);
});