gulp-beginner-guide

开始写gulp任务

写gulp任务的基本语法

1
2
3
gulp.task('task-name',function(){
//do sth here
});

一般的gulp任务包含2个gulp方法,和不同的Gulp插件。
一个真正的任务看起来像这样:

1
2
3
4
5
gulp.task('task-name',function(){
return gulp.src('source-files') //get source files with gulp.src
.pipe(someGulpPlugin()) //send it through a gulp plugin
.pipe(gulp.dest('destination'))//output the file in the destination folder
})

一般真正的任务需要2个额外的方法 — gulp.src 和 gulp.test。
gulp.src告诉Gulp任务处理什么文件,gulp.dest告诉Gulp,当任务完成时候,输出的文件放哪里。

用gulp预处理(preprocessing)

使用gulp-sass插件可以将sass编译为css。
先安装。

1
npm install gulp-sass --save-dev

从node_modules文件夹require gulp-sass,才能使用。

1
2
3
var gulp = require('gulp');
// Requires the gulp-sass plugin
var sass = require('gulp-sass');

用sass()方法使用gulp-sass。

1
2
3
4
5
gulp.task('sass',function(){
return gulp.src('source-files')
.pipe(sass()) //using gulp-sass
.pipe(gulp.dest('destination'))
});

我们需要给sass任务一个源文件和目标文件。在app/scss文件夹创建一个styles.scss。这个文件会被gulp.src添加到sass任务。

1
2
3
4
5
gulp.task('sass',function(){
return gulp.src('app/scss/styles.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
})

在命令行运行 gulp sass,可以看见在app/css下创建了一个styles.css。
Gulp-sass使用LibSass将Sass编译成CSS。比基于ruby的方法快。

Glob in Node

Globs是匹配模式,允许你添加多个文件到gulp.src。有点像正则表达式,但只是针对文件路径。

当你使用glob,电脑会为这个模式检查文件名和路径。如果模式存在,文件就匹配上了。
大部分的Gulp工作流只需要4种不同的globbing patterns:

  1. *.scss : *就是通配符,匹配当前目录下的任何模式。在这种情况下,我们匹配根目录下任意以 .scss 结尾的文件。
  2. **/*.scss : 这是一个更极端的版本。匹配根目录下或者任意子目录下的 .scss 结尾的文件。
  3. !not-me.scss : “!”表示Gulp需要从匹配中排除该模式。如果你不需要匹配的模式中的某一个文件,这很有用。这个例子中,not-me.scss 会从匹配中移除。
  4. *.+(scss|sass) : 加号和括号允许Gulp匹配多个模式。不同的模式用pipe | 分隔开。这个例子,Gulp会匹配根目录下任意以 .scss.sass 结尾的文件。

知道了golbbing,可以将原来的 app/scss/styles.scss 替换为 scss/**/*.scss 模式。这样就可以匹配任意在根目录下或者子目录下文件扩展名为 .scss 的文件了。

1
2
3
4
5
gulp.task('sass',function(){
return gulp.src('app/scss/**/*.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
});

任意在app/scss目录下的sass文件,会被自动添加到这个任务。
现在,我们只用一个命令就可以将所有的sass文件编译成css。
可是,每次想要把sass编译为css都要手动运行一遍 gulp sass ,这样太麻烦了。

幸运的是,每当文件发生变化,Gulp可以自动运行 sass 任务,如果这个文件被一个叫做’watching’的进程。

Watching Sass files for changes(监视sass文件的改变)

Gulp提供了一个 watch 方法看一个文件是否保存。 watch 方法的语法如下:

1
2
// Gulp watch syntax
gulp.watch('files-to-watch',['task', 'to', 'run']);

想要监视所有Sass文件并在每次一个Sass 文件保存的时候运行 sass 任务,只需要将 files-to-watch 换成 app/scss/**/*.scss ,把 ['tasks', 'to', 'run'] 换成 ['sass']

1
gulp.watch('app/scss/**/*.scss',['sass']);

然而大多数时候,我们需要一次监视多种类型的文件。
我们可以将多个监视任务组合成一个 watch 任务:

1
2
3
4
gulp.task('watch',function(){
gulp.watch('app/scss/**/*.scss',['sass'])
// other watchers
})

可以运行 gulp watch 立刻运行监视任务。
每次保存一个 .scss 文件,都会运行 sass 任务。

Live-reloading with Browser Sync

先安装:

1
npm install browser-sync --save-dev

注意安装的时候没有 gulp- 前缀。这是因为Gulp和Browser Sync一起工作,所以不需要使用插件。
使用前需要require:

1
var browserSync = require('browser-sync').create();

告诉 watch 任务,必须在 browserSync 完成之后才能运行。
我们可以给 watch 任务添加一个参数来达到这个目的:

1
gulp.task('watch',['arrays', 'of', 'tasks', 'to', 'complete', 'before', 'watch'],function(){})

比如:

1
2
3
4
gulp.task('watch',['browserSync'],function(){
gulp.task('app/scss/**/*.scss',['scss']);
// other watchers
})

保证 sass 任务在 watch 之前运行,这样,无论什么时候运行gulp命令css都是最新的。

1
2
3
4
gulp.task('watch',['browserSync','sass'],function(){
gulp.watch('app/scss/**/*.scss',['scss']);
// other watchers
});

现在在命令行运行 gulp watch ,gulp会同时开启 sassbrowserSync 任务。当这两个任务都完成了, watch 才开始运行。

同时,指向 app/index.html 的浏览器窗口会弹出。如果修改 styles.scss 文件, 浏览器会自动重载。
当html和js文件保存的时候,也重载。

1
2
3
4
5
6
gulp.task('watch',['browserSync', 'sass'],function(){
gulp.watch('app/scss/**/*.scss',['sass']);
// reload the browser whenever HTML or JS files change
gulp.watch('app/*.html',browserSync.reload);
gulp.watch('app/js/**/*.js',browserSync.reload);
});

目前为止,做成了3件事情:

  1. 生成开发服务器
  2. 使用Sass预处理程序
  3. 每当文件发生改变,重载浏览器。

接下来优化资源,先从css和js文件开始。

优化CSS和JS文件

优化css和js的时候,开发者需要做2件事情:minification and concatenation。
开发者经常遇到的问题是不能按照正确的顺序来连接这些文件。
比如:

1
2
3
4
5
6
<body>
<!-- stuff -->
<script src"js/lib/a-xxx.js"></script>
<script src"js/lib/b-xxx.js"></script>
<script src"js/main.js"></script>
</body>

这些文件不在同一个目录下。很难用传统的插件比如gulp-concatenate串联。
很幸运,现在有一个插件,叫做gulp-useref能够解决这个问题。
Gulp-useref将任意数量的css和js文件并为一个文件。
语法如下:

1
2
3
<!-- build:<type> <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->

<type> 可以是 js , css , 或者 remove 。最好是把type设置为试图串联的文件类型。如果把 type 设置为 remove ,Gulp会删除整段代码,不会生成文件。
<path> 只得是生成文件的目标路径。
我们想要js文件到 js 文件夹,名字为 main.min.js ,标记可以这样写:

1
2
3
4
5
<!-- build:js js/main.min.js -->
<script src"js/lib/a-xxx.js"></script>
<script src"js/lib/b-xxx.js"></script>
<script src"js/main.js"></script>
<!-- endbuild -->

现在来配置gulp-useref。先安装,再在gulpfile中require。

1
npm install gulp-useref --save-dev

1
var useref=require('gulp-useref');

设置 useref 任务:

1
2
3
4
5
gulp.task('useref',function(){
return gulp.src('app/*html')
.pipe(useref())
.pipe(gulp.dest('dist'))
})

运行useref任务,Gulp会把这三个文件串联为一个,放到 dist/js/main.min.js
现在文件还没有压缩。使用gulp-uglify插件压缩js文件,还需要gulp-if保证只压缩js。

1
npm install gulp-uglify --save-dev

1
2
3
4
5
6
7
8
9
10
11
// other requires...
var uglify=require('gulp-uglify');
var gulpIf=require('gulp-if');

gulp.task('useref',function(){
return gulp.src('app/*.html')
.pipe(useref())
// minifies only if it's a javascript file
.pipe(gulpIf('*.js',uglify()))
.pipe(gulp.dest('dist'))
});

现在每次运行 useref ,都会自动压缩js。
可以用同样的方法串联css文件。

1
2
3
4
<!-- build:css css/style.min.css -->
<link ref="stylesheet" href="css/styles.css">
<link ref="stylesheet" href="css/another-styles.css">
<!-- end build -->

用gulp-cssnano插件压缩css文件:

1
npm install gulp-cssnano --save-dev

1
2
3
4
5
6
7
8
var cssno=require('gulp-cssnano');
gulp.task('useref',function(){
return gulp.src('app/*.html')
.pipe(useref())
.pipe(gulpIf('*.js',uglify()))
.pipe(gulpIf('*.css',cssnano()))
.pipe(gulp.dest('dest'))
});

现在每次运行 useref 就优化css和js文件。
接下来,我们优化图片。

优化图片

使用gulp-imagemin优化图片。

1
npm install gulp-imagemin --save-dev

1
var imagemin = require('gulp-imagemin');

可以用gulp-imagemin压缩png,jpg,gif甚至是svg文件。

1
2
3
4
5
gulp.task('images',function(){
return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
.pipe(imagemin())
.pipe(gulp.dest('dist/images'))
});

不同的文件类型优化得不同,所以可能需要给不同的文件类型配置不同的优化选项。
比如:

1
2
3
4
5
6
7
8
gulp.task('images',function(){
return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg')
pipe(imagemin({
// setting interlaced to true
interlaced:true
}))
.pipe(gulp.dest('dist/images'))
});

优化图片很慢,没有必要每次都优化。用gulp-cache来达到这个目的:

1
npm install gulp-cache --save-dev

1
2
3
4
5
6
7
8
9
10
var cache=require('gulp-cache');

gulp.task('images',function(){
return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
// caching images that ran through imagemin
.pipe(cache(imagemin({
interlaced:true
})))
.pipe(gulp.dest('dist/images'))
});

基本搞定。还有一个需要到’dist’文件夹的东西:fonts。

复制字体到dist文件夹

字体已经优化了。我们不需要再做什么。
用gulp复制文件:

1
2
3
4
gulp.task('fonts',function(){
return gulp.src('app/fonts/**/*')
.pipe(gulp.dest('dist/fonts'))
})

现在每次运行 gulp fonts 都会将字体从app文件夹复制到dist文件夹。

现在已经有6个不同任务了。每个任务都单独地在命令行运行,这样有点繁琐。

自动清除生成到文件

确保不用到文件不会保留在我们不知道到地方。

1
npm install del --save-dev

1
var del=require('del');

del 任务删除任意数组的node globs文件夹。

1
2
3
gulp.task('clean:dist',function(){
return del.sync('dist');
})

现在每次运行 gulp clean:dist 就会删除dist文件夹。
不用担心回删除 dist/images ,因为gulp-cache已经在本地系统保存了图片的缓存。
要删除本地系统的缓存,可以创建一个清除缓存的任务。

1
2
3
gulp.task('cache:clear',function(callback){
return cache.clearAll(callback)
})

Combing Gulp Tasks(组合gulp任务)

总结一下,目前我们做了2种不同类型gulp任务。
第一种是开发过程中,把sass编译为css,监视变化,每次重载浏览器。
第二中是优化过程,此时我们已经准备好了所有生产网站所需的文件。我们优化好css,js和图片,复制字体。

第一组任务用 gulp watch 命令行合为一个工作流了。

1
2
3
gulp.task('watch',['browserSync','sass'],function(){
// ...watchers
})

第二组任务包含创建生产网站的任务: clean:dist , sass , useref , images , 和 fonts

要保证cleans在其他任务完成之前完成,我们需要一个插件Sequence。

1
npm install run-sequence --save-dev

语法如下:

1
2
3
4
var runSequence=require('run-sequence');
gulp.task('task-name',function(callback){
runSequence('task-one','task-two','task-three',callback);
});

当调用 task-name 的时候,gulp会先运行 task-onetask-one 运行完成,gulp会自动开始运行 task-twotask-two 完成,运行 task-three
如果把任务放在一个数组里面,会同时运行这些任务。

1
2
3
gulp.task('task-name',function(callback){
runSequence('task-one',['tasks','two','in','run','in','parallel'],'task-three',callback);
});

这样,gulp先运行 task-one ,当第一个任务运行完成,gulp会同时运行第二个参数里面的任务。当数组里面所有的任务都运行完成,才会开始运行 task-three
现在可以创建一个任务,保证 dist:clean 先运行,然后再运行其他的任务。

1
2
3
4
5
6
gulp.task('build',function(callback){
runSequence('clean:dist',
['sass','useref','images','fonts'],
callback
)
})

为了保证一致性,第一组任务我们也可以创建顺序。

1
2
3
4
5
gulp.task('default',function(callback){
runSequence(['sass','browserSync','watch'],
callback
)
})

default ,你只需要键入 gulp 在命令行。

[原文链接]: (https://css-tricks.com/gulp-for-beginners/ )