跳到主要内容

尚硅谷前端Gulp教程学习笔记

· 阅读需 10 分钟

这篇文章是尚硅谷前端Gulp教程的学习笔记。

环境搭建

教程使用的Gulp是3.9,而现在Gulp已经升级到了4.0,改动较大,但是并不影响学习。为了避免环境不一致导致的各种坑,可以安装和教程一致的版本。目前,Node.js的LTS版本为v12.16,已经不兼容Gulp 3.9了,如果Node.js版本过新,会报错:

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:

$ nvm install v11.15.0
$ nvm use v11.15.0

在WebStorm中新建Node.js项目,项目目录下会有package.json,编辑之,内容如下:

{
"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"
}
}

然后执行以下命令:

$ 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在运行时会读取该文件并执行对应的操作。

如果注册普通任务,则在运行时需要指定任务名;如果注册默认任务,则在运行时不需要指定任务名。

var gulp = require('gulp');

// 注册任务
gulp.task('task_name', function () {
// 配置任务的操作
});

// 注册默认任务
gulp.task('default', []);
# 运行指定任务
$ gulp task_name
# 运行默认任务
$ gulp

基本使用

构建js

任务需求:合并多个js文件,压缩js文件并将后缀重命名为.min.js

这些功能依赖Gulp插件:gulp-concatgulp-uglifygulp-rename

假设js源文件都位于src/js/下,将最后得到的文件存为dist/js/build.min.js。编辑gulpfile.js,内容如下:

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文件,然后运行:

$ gulp js

2020-05-24T03:12:49.png

即可在dist/js/下看到构建好的build.min.js了。

如果要递归搜素目录下的js文件,gulp.src里的路径可以写为src/js/**/*.js。压缩js会移除冗余的js代码。

构建Less

任务需求:编译lesscss。可以使用gulp-less插件来完成。

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后缀。

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

gulp.task('default', ['js', 'less', 'css']);

注意:Gulp 4.0已不支持这种写法,会报错:

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中通过第二个参数指定依赖的任务,如下:

gulp.task('css', ['less'], function() {
// do something
});

这样在运行css任务前,会先执行less任务,因此在默认任务里就不需要less任务了。

压缩HTML

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监视文件改动:

// ... 为了排版美观,省略了部分代码,下同
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())

// ... 为了排版美观,省略了部分代码,下同
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-前缀,将带-的插件名改为驼峰命名的方式即可。以下是部分替换表:

gulp-concat -> $.concat
gulp-htmlmin -> $.htmlmin
gulp-clean-css -> $.cleanCss

当然,gulp-load-plugins插件本身还是需要加载的,需要注意的是它是个函数,后面需要加上()

var $ = require('gulp-load-plugins')();