这篇文章是尚硅谷前端Gulp教程的学习笔记。
环境搭建
教程使用的Gulp是3.9,而现在Gulp已经升级到了4.0,改动较大,但是并不影响学习。为了避免环境不一致导致的各种坑,可以安装和教程一致的版本。目前,Node.js的LTS版本为v12.16,已经不兼容Gulp 3.9了,如果Node.js版本过新,会报错:
1
2
3
4
5
| fs.js:35
} = primordials;
^
ReferenceError: primordials is not defined
|
为了更优雅地管理Node.js的版本,推荐使用nvm。Node.js v11.15.0和Gulp 3.9是兼容的,可以安装此版本。安装nvm后,执行下面的命令安装Node.js v11.15:
1
2
| $ nvm install v11.15.0
$ nvm use v11.15.0
|
在WebStorm中新建Node.js项目,项目目录下会有package.json
,编辑之,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| {
"name": "gulp-learn",
"version": "1.0.0",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-clean-css": "^3.9.0",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.0.0",
"gulp-htmlmin": "^3.0.0",
"gulp-less": "^3.3.2",
"gulp-livereload": "^3.8.1",
"gulp-load-plugins": "^1.5.0",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^3.0.0",
"open": "0.0.5"
}
}
|
然后执行以下命令:
1
2
| $ npm install -D
$ npm install -g gulp@3.9.1
|
Gulp简介
个人觉得Gulp和make是类似的,它们都可以定义一些任务,任务之间可以定义一些依赖关系,然后指定任务进行自动构建。不同的是,make是通过组合Shell命令的方式实现任务,一般用于C++程序编译;而Gulp则是通过组合Gulp插件的方式实现任务,一般用于网页静态资源构建。Gulp能自动化完成javascript、sass、less、css等文件的合并、压缩、检查、监听文件变化、浏览器自动刷新、测试等任务。
核心API
gulp.task
用于定义任务gulp.src
用于将源文件读取到Gulp内存区域gulp.dest
用于输出文件gulp.watch
用于监听文件变化gulp.pipe
也就是管道,用于传递处理的文件
注册任务
在项目目录下新建gulpfile.js
,这个文件定义Gulp的任务,Gulp在运行时会读取该文件并执行对应的操作。
如果注册普通任务,则在运行时需要指定任务名;如果注册默认任务,则在运行时不需要指定任务名。
1
2
3
4
5
6
7
8
9
| var gulp = require('gulp');
// 注册任务
gulp.task('task_name', function () {
// 配置任务的操作
});
// 注册默认任务
gulp.task('default', []);
|
1
2
3
4
| # 运行指定任务
$ gulp task_name
# 运行默认任务
$ gulp
|
基本使用
构建js
任务需求:合并多个js文件,压缩js文件并将后缀重命名为.min.js
。
这些功能依赖Gulp插件:gulp-concat
、gulp-uglify
、gulp-rename
假设js源文件都位于src/js/
下,将最后得到的文件存为dist/js/build.min.js
。编辑gulpfile.js
,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
| var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
gulp.task('js', function () {
return gulp.src('src/js/*.js') /* 找到源文件,加载到gulp内存 */
.pipe(concat('build.js')) /* 临时合并文件 */
.pipe(gulp.dest('dist/js/')) /* 输出到本地 */
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('dist/js/'))
});
|
在src/js/
下添加一些js文件,然后运行:

即可在dist/js/
下看到构建好的build.min.js
了。
如果要递归搜素目录下的js文件,gulp.src
里的路径可以写为src/js/**/*.js
。压缩js会移除冗余的js代码。
构建Less
任务需求:编译less
为css
。可以使用gulp-less
插件来完成。
1
2
3
4
5
6
7
8
9
| var gulp = require('gulp');
var less = require('gulp-less');
/* 注册转换less的任务 */
gulp.task('less', function () {
return gulp.src('src/less/*.less')
.pipe(less()) /* 使用less编译,文件后缀自动转为.css */
.pipe(gulp.dest('src/css/'))
})
|
less
编译时,会自动将编译后的文件重命名为.css
后缀,所以不需要rename
。
构建CSS
任务需求:合并多个CSS文件,然后压缩并重命名为.min.css
后缀。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| var gulp = require('gulp');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var cssClean = require('gulp-clean-css');
// 注册合并压缩css文件
gulp.task('css', function () {
return gulp.src('src/css/*.css')
.pipe(concat('build.css'))
// 压缩与重命名可以顺序对调
.pipe(rename({suffix: '.min'}))
.pipe(cssClean({compatibility: 'ie8'}))
.pipe(gulp.dest('dist/css/'))
})
|
注册默认任务
任务需求:运行gulp
变自动执行任务js、less、css
1
| gulp.task('default', ['js', 'less', 'css']);
|
注意:Gulp 4.0已不支持这种写法,会报错:
1
2
3
4
5
| assert.js:385
throw err;
^
AssertionError [ERR_ASSERTION]: Task function must be specified
|
运行gulp
就能执行这个默认任务了。它会启动default、js、less、css任务,不过,任务并不会等待前一个任务结束后才启动,这说明它们是异步执行的。如果删掉return
,就会同步执行,不过由于return
可以清理gulp内存,一般还是建议加上return
。
不过,css任务是需要等待less任务结束后才能开始的,也就是css任务依赖less任务的完成,对于这样的有依赖的任务,可以在task中通过第二个参数指定依赖的任务,如下:
1
2
3
| gulp.task('css', ['less'], function() {
// do something
});
|
这样在运行css任务前,会先执行less任务,因此在默认任务里就不需要less任务了。
压缩HTML
1
2
3
4
5
6
7
8
| var gulp = require('gulp');
var htmlMin = require('gulp-htmlmin');
gulp.task('html', function () {
return gulp.src('index.html')
.pipe(htmlMin({collapseWhitespace: true}))
.pipe(gulp.dest('dist/'));
})
|
半自动构建
任务需求:监听文件改动,自动执行默认构建
使用gulp-livereload
插件。首先,在相关的任务里接上.pipe(livereload())
,然后启动监听,并通过gulp.watch
监视文件改动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| // ... 为了排版美观,省略了部分代码,下同
var livereload = require('gulp-livereload');
gulp.task('js', function () {
// ...
.pipe(livereload())
});
/* 注册转换less的任务 */
gulp.task('less', function () {
return gulp.src('src/less/*.less')
.pipe(less()) /* 使用less编译,文件后缀自动转为.css */
.pipe(gulp.dest('src/css/'))
.pipe(livereload())
})
/* 注册合并压缩css文件 */
gulp.task('css', ['less'], function () {
// ...
.pipe(livereload())
})
/* 注册半自动监视任务 */
gulp.task('watch', ['default'], function () {
/* 开启监听 */
livereload.listen();
/* 确认监听的目标以及绑定相应的任务 */
gulp.watch('src/js/*', ['js']);
gulp.watch(['src/css/*.css', 'src/less/*.less'], ['css']);
});
|
全自动构建
在半自动构建中,我们仍需手动打开浏览器并刷新,在本节可以将这些操作也自动化。为了实现自动打开浏览器,可以使用open
完成(注意它不是gulp插件);为了在修改文件后自动构建并自动刷新,可以使用插件gulp-connect
来完成,它内置了一个小型server。为此,还需要在相关的任务里接上.pipe(connect.reload())
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| // ... 为了排版美观,省略了部分代码,下同
var livereload = require('gulp-livereload');
var connect = require('gulp-connect');
var open = require('open');
gulp.task('js', function () {
// ...
.pipe(livereload())
.pipe(connect.reload())
});
/* 注册转换less的任务 */
gulp.task('less', function () {
return gulp.src('src/less/*.less')
.pipe(less()) /* 使用less编译,文件后缀自动转为.css */
.pipe(gulp.dest('src/css/'))
.pipe(livereload())
.pipe(connect.reload())
})
/* 注册合并压缩css文件 */
gulp.task('css', ['less'], function () {
// ...
.pipe(livereload())
.pipe(connect.reload())
})
/* 注册全自动监视任务 */
gulp.task('server', ['default'], function () {
/* 配置服务器的选项 */
connect.server({
root: 'dist/', /* 配置根目录 */
livereload: true, /* 实时刷新 */
port: 5000,
});
open('http://localhost:5000/');
gulp.watch('src/js/*', ['js']);
gulp.watch(['src/css/*.css', 'src/less/*.less'], ['css']);
})
|
自动加载插件
可以使用gulp-load-plugins
插件自动加载需要的插件,而不需要显式require各插件,使用$.插件名
的方式直接使用插件,不需要gulp-
前缀,将带-
的插件名改为驼峰命名的方式即可。以下是部分替换表:
1
2
3
| gulp-concat -> $.concat
gulp-htmlmin -> $.htmlmin
gulp-clean-css -> $.cleanCss
|
当然,gulp-load-plugins
插件本身还是需要加载的,需要注意的是它是个函数,后面需要加上()
。
1
| var $ = require('gulp-load-plugins')();
|