Gulp快速入门

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插件

$ 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']);
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351