gulp入门+ES6

jopen 9年前


Gulp是一个基于 nodejs stream 的流式前端构建工具,与Grunt功能相同,专注于前端资源的编译、检查、压缩等自动化工作。

安装gulp

安装gulp之前,更新一下npm(可选,避免因版本过低报错):

curl https://www.npmjs.org/install.sh | sudo sh

使用npm安装gulp到全局:

npm install -g gulp

使用npm安装gulp到当前项目的node_modules, 并更新package.json配置信息:

npm install --save-dev gulp

编写gulpfile.js

最简单的gulpfile.js结构:

var gulp = require('gulp');    gulp.task('task-name', function() {      console.log('Hello, Gulp!');   });

在gulpfile.js所在路径的终端输入gulp task-name就可以看到Hello, Gulp!了,这个示例没有实际作用,纯粹是为了演示gulpfile.js的基本结构。

下面我们使用 gulp 实现一个实用功能:编译 Sass,并添加浏览器前缀。首先,初始化一个演示目录:

  • mkdir gulp-in-action,创建演示目录gulp-in-action
  • cd gulp-in-action,进入演示目录gulp-in-action
  • mkdir sass,创建 Sass 目录sass
  • touch sass/demo.scss,创建 Sass 文件demo.scss用于演示
  • touch gulpfile.js,创建 gulp 的配置文件gulpfile.js
  • tree .,以树状图的形式展示当前目录结构

gulp入门+ES6

然后,安装依赖gulp、gulp-sass和gulp-autoprefixer:

npm install --save-dev gulp gulp-sass gulp-autoprefixer

其中,gulp-sass用于将 Sass 文件编译为 CSS 文件,gulp-autoprefixer用于为 CSS 属性添加适当的浏览器前缀。此外,在正式的开发项目中,应该使用npm init或者自建方式创建一个package.json存储依赖关系等配置信息,当然,如果想要获得更优秀的脚手架,你可以尝试一下yeoman(号称现代前端开发的脚手架)。

接下来,使用熟悉的编辑器打开gulpfile.js,编写 gulp 的自动化构建逻辑:

// 导入 gulp/gulp-sass/gulp-autoprefixer 三个模块  var gulp = require('gulp');  var sass = require('gulp-sass');  var autoprefixer = require('gulp-autoprefixer');  // 使用 gulp.task() 方法注册一个任务  // 第一个参数是任务名称  // 第二个参数是任务的执行逻辑  gulp.task('styles', function() {   return gulp.src('sass/demo.scss')    .pipe(sass())    .pipe(autoprefixer())    .pipe(gulp.dest('css'));  });

在继续下面的操作之前,我们有必要认识一下 gulp 中的五大函数:

  • gulp.task(name, fn),注册一个 gulp 任务
  • gulp.run(...tasks),并行运行多个 gulp 任务
  • gulp.watch(glob, fn),实时监控内容,当glob内容变化时,执行fn
  • gulp.src(glob),glob是目标文件的路径,返回一个可读的 stream
  • gulp.dest(gloc),glob是输出路径,返回一个可写的 stream

那么,什么是pipe()呢?先来看一个unix命令:

cat gulpfile.js | wc -l

这是一条由管道符(|)拼接起来的命令,整体由两部分组成,每一部分都是一条独立的命令:cat gulpfile.js用来获取gulpfile.js的文件内容;wc -l用来统计文件中的行数。管道符(|)在这里的作用是拼接两条命令,将前者(cat gulpfile.js)的输出,作为后者的wc -l的输入。

gulp 中使用的pipe()函数就是模拟了管道符的操作方式,比如下面的 gulp 命令:

gulp.src('sass/demo.scss')      .pipe(sass())      .pipe(autoprefixer())

就可以想象为:

'sass/demo.scss' | sass() | autoprefixer()

基础知识介绍完了,最后我们来执行 gulp 任务,终端中输入:

gulp styles

这里的styles就是gulpfile.js中注册过的任务名称。如果配置文件没有错误地话,执行完成后项目结构如下:

gulp入门+ES6

编译之前,sass/demo.scss的内容如下:

.container {      display: flex;  }

编译之后,打开css/demo.css文件,内容如下:

.container {   display: -webkit-box;   display: -webkit-flex;   display: -ms-flexbox;   display: flex;   }

可见,gulp styles已经自动完成了 Sass 到 CSS 的编译,并添加了适当的浏览器前缀。

接下来,我们使用gulp.watch()函数优化一下自动化任务,让 Sass 文件每次发生改动时可以自动编译。gulp 官方插件开发说明中建议开发者遵循单一职责原则,所以,我们这里实现watch任务最好的方式就是借助styles任务的功能,增加下面的代码到gulpfile.js配置文件中:

gulp.task('watch', function() {      gulp.watch('sass/demo.scss', ['styles']);  });

然后在终端运行gulp watch命令,即可实时修改实时编译了。到此,我们基本实现了既定的自动化目标,当然,只做这么点工作就太让 gulp 屈才了,不过本文定位为入门文章,更多更深入的使用方式,建议学习慕课网 《Grunt-beginner前端自动化工具》 一课,内容全面深入浅出,值得一学。

gulp.watch()

gulp.watch()可以返回一个监听对象,用来监听额外的事件,比如change:

var watcher = gulp.watch('sass/*.scss');  watcher.on('change', function (event) {      console.log('Event type: ' + event.type);      console.log('Event path: ' + event.path);  });

其他事件:

  • nomatch,在glob没有匹配到文件时触发
  • ready,在匹配后即将进行自动化任务前触发
  • error,自动化任务出错时触发
  • end,自动化任务完成时触发

watcher对象可以调用的一些方法:

  • watcher.end(),中断watcher
  • watcher.files(),返回监听的文件列表
  • watch.add(glob[, fn]),添加文件到监听的文件列表
  • watch.remove(fillpath),从监听的文件列表中移除文件

node-glob

在上面的gulp.src(glob)和gulp.dest(glob)函数中,glob参数既可以是具体的路径,也可以是一些路径规则,通常来说,路径规则比具体路径更常用,也更灵活,最常见的符号就是通配符(*),比如sass/*.scss表示匹配sass文件夹下所有以.scss作为后缀的文件。

gulp 中使用 gulp-glob 来匹配文件,下面列出几种最常见的匹配方式:

  • sass/demo.scss,精确匹配sass文件夹下的demo.scss文件
  • sass/*.scss,匹配sass文件夹下所有以.scss作为后缀的文件
  • sass/**/*.scss,匹配sass文件夹以及子文件夹下所有以.scss作为后缀的文件
  • !sass/demo.scss,!后面跟上述三种模式,可以充匹配结果中排除相关文件,比如这里的!sass/demo.scss表示从匹配结果中排除sass文件夹下的demo.scss文件
  • sass/*.+(sass|scss),匹配sass文件夹下所有以.scss和.sass作为后缀的文件

这些规则和正则表达式有相似之处,更多信息可以参考 minimatchnode-glob中文版 )的官方文档。

常用插件

目前在 gulp 的官方 插件页面 ,已经可以搜索到多达 1800+ 的插件,当你需要使用某种插件时,建议优先使用该页面搜索一下是否有现成的插件可用,然后再考虑造轮子,避免重复工作。

下面列举一些常用插件,善用这些插件才能让 gulp 发挥出最大作用。

gulp-load-plugins

在我们的gulpfile.js中,每当需要使用新的插件时,就需要在头部声明并加载一次,如果依赖的插件较多,维护起来就会比较困难,gulp-load-plugins插件就是针对这一问题而存在的,安装方式:

npm install --save-dev gulp-load-plugins

接下来,我们在gulpfile.js中使用gulp-load-plugins替代导入依赖的方式:

// var sass = require('gulp-sass');  // var autoprefixer = require('gulp-autoprefixer');  var $ = require('gulp-load-plugins')();  gulp.task('styles', function() {   return gulp.src('sass/demo.scss')    .pipe($.sass())    .pipe($.autoprefixer())    .pipe(gulp.dest('css'));  });

之后再有新的依赖加入开发环境,也无需增加头部的声明,调用即可使用。

使用gulp-load-plugins,必须保证项目依赖都写在了package.json中,这是因为gulp-load-plugins的加载核心就是调用package.json的配置信息。 如果你不知道怎么创建一份package.json,那么我们可以做一个游戏,在终端输入npm init试一试。

browsersync

browsersync是一款浏览器实时测试工具,它可以嵌入到多种自动化构建工具中,详细的使用方式请参考 官方文档 。安装方式:

npm install --save-dev browser-sync

重写gulp watch任务:

gulp.task('watch', function() {   browserSync.init({    server: {     baseDir: "./"    }   });   gulp.watch('sass/demo.scss', ['styles'])    .on('change', browserSync.reload);  });

在项目根目录下创建一个index.html用于演示项目:

<!DOCTYPE html>  <html lang="en">  <head>   <meta charset="UTF-8">   <title>Document</title>   <link rel="stylesheet" href="css/demo.css">  </head>  <body>   <p>help</p>  </body>  </html>

为了更明显的查看效果,我们修改demo/sass.scss的内容为:

body {      background-color: red;  }

终端运行gulp watch即可自动打开浏览器,实时修改页面的效果:

gulp入门+ES6

学习和使用插件最有效地方式就是去相关的文档,然后投入到实际开发中……这里仅仅列出列出几个插件,后续会随着对 gulp 理解的深入继续增加更多插件。

gulp + ES6

在最新的 gulp 3.9 版本上,开发者可以使用 ES6(ES2015) 语法 来编写配置文件了。第一步,先检查一下 CLI 和本地版本:

gulp -v  // => CLI version 3.9.0  // => Local version 3.9.0

第二步,在终端安装依赖Babel:

npm install babel-core --save-dev

第三步,将gulpfile.js重名为gulpfile.babel.js:

mv "gulpfile.js" "gulpfile.babel.js"

下面展示一个使用 ES6 语法编写的gulpfile.babel.js,其中有箭头函数、模块导入、常量声明和模板字符串(更喜欢叫它插值字符串)等新语法:

import gulp from 'gulp';  import sass from 'gulp-sass';  import autoprefixer from 'gulp-autoprefixer';  const dirs = {   src: 'scss',   dest: 'css'  };  const sassPaths = {   src: `${dirs.src}/demo.scss`,   dest: `${dirs.dest}`  };  gulp.task('styles', () => {   return gulp.src(paths.src)    .pipe(sass.())    .pipe(autoprefixer())    .pipe(gulp.dest(paths.dest));  });

如果遵循上述步骤遇到了未知错误,可以尝试安装babel代替babel-core来解决:

npm install babel --save-dev

参考资料

gulp入门+ES6

南北

在校学生,本科计算机专业。狂热地想当一名作家,为色彩和图形营造的视觉张力折服,喜欢调教各类JS库,钟爱CSS,希望未来加入一个社交性质的公司,内心极度肯定“情感”在社交中的决定性地位,立志于此改变社交关系的快速迭代。 个人博客