04_gulp介绍

环境

Centos 7 X86_64(虚拟机)

初始化

# yum install epel -y
# yum install vim nodejs npm -y

安装gulp

# npm install gulp --global

package.json

创建package.json配置文件(package.json是用来记录项目依赖组件的配置文件.)

# npm init      # 根据提示一步一步定义最基本的配置文件.

//下面配置完成之后的内容.
{
  "name": "normandy",
  "version": "1.0.0",
  "description": "bai yuan web projects",
  "main": "index.js",
  "scripts": {
    "test": "echo \\\"Error: no test specified\\\" && exit 1"
  },
  "author": "",
  "license": "ISC",
}

维护package.json

常规的维护可以通过vim或者直接用编辑器对package.json文件进行编辑,只有当需要为项目固化依赖组建时才会使用到下面这个命令来更新package.json.

# npm install npm install gulp gulp-buffer gulp-clean-css --save-dev

// 下面是配置更新后的内容.
{
  "name": "normandy",
  "version": "1.0.0",
  "description": "bai yuan web projects",
  "main": "index.js",
  "scripts": {
    "test": "echo \\\"Error: no test specified\\\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.24.0",
    "babel-preset-es2015": "^6.24.0",
    "gulp": "^3.9.1",
    "gulp-buffer": "0.0.2",
    "gulp-clean-css": "^3.0.3",
  }
}

Gulp编程

Gulp可以将指定目录下的文件或者正则匹配到的文件进行读取,然后以数据流形式通过管道可以与其他命令协作完成对项目文件的定制。官方明确表示它仅仅是一个基础的任务管理系统。这段话读起来有点绕口,gulp将它拆成了四个命令(gulp.task、gulp.src、gulp.dest、gulp.watch),下面单独对着四个命令进行简单描述(另外在延伸gulp的pipe属性方法和through插件库)。

Gulp.task

Gulp.task只负责执行命令, 其他的什么都不管, 运行Gulp.task不需要有任何准备, 不对任何文件和目录结构有要求。它仅仅是一个命令执行方法。

javascript的写法: gulpfile.js

var gulp = require('gulp');
gulp.task('hello_javascript', function() {
    console.log('hello JavaScript!')
})

ECMAScript的写法: gulpfile.babel.js

import gulp from 'gulp';
gulp.task('hello_ecmascript', () => {
    console.log('hello ECMAScript');
})

# 输出结果
[root@localhost ~]# gulp hello_ecmascript
[04:40:30] Requiring external module babel-register
[04:40:30] Using gulpfile ~/gulpfile.babel.js
[04:40:30] Starting 'hello_ecmascript'...
hello ECMAScript
[04:40:30] Finished 'hello_ecmascript' after 324 μs

语法: gulp.task(name [, deps] [, fn])
name和[, fn]着两个参数已经在上面两个例子中有使用过了,
[, deps]尚未使用,它主要的作用是控制执行顺序,
例如:gulp.task('hello_ecmascript', ['hello_javascript'], () => { ... })这个任务的意思是说, 在执行hello_ecmascript之前需要先执行hello_javascript

Gulp.pipe

管道(pipe)用于传输文件字节流(数据流),gulp默认采用了vinyl-fs来处理文件对象,而vinyl-fs采用through2来处理数据流;在处理多文件的数据流这件事情上gulp一般都脱离不了through2。参考网址
through2会将gulp.src指定的多个文件(例如: gulp.src('src/*.js')),通过回调的方式挨个挨个将文件对象传递给through2,下面举两个例子来介绍pipe属性方法和through2的工作原理。

文件合并(gulp-concat)

# 创建一个案例目录
[root@localhost ~]# mkdir -p simple_merge/src
[root@localhost ~]# cd simple_merge/

# 安装gulp和react
[root@localhost simple_merge]# cnpm install gulp gulp-concat vue react --save-dev

# 将react.js和vue复制到src目录
[root@localhost simple_merge]# cp node_modules/react/dist/react.js node_modules/vue/dist/vue.js src/

# 撰写gulpfile.js文件
[root@localhost simple_merge]# vim gulpfile.js
var gulp   = require('gulp'),
    concat = require('gulp-concat')

gulp.task('compress', function() {
    return gulp.src('src/*.js')
           .pipe(concat('bundle.js'))
           .pipe(gulp.dest('dist/'))
})

# 构建(文件合并)
[root@localhost simple_merge]# ./node_modules/gulp/bin/gulp.js compress
[20:13:51] Using gulpfile ~/fron_end/simple_merge/gulpfile.js
[20:13:51] Starting 'compress'...
[20:13:51] Finished 'compress' after 51 ms

# 查看当前目录结构
[root@localhost simple_merge]# ls
dist  gulpfile.js  node_modules  package.json  src

# 查看dist目录结构
[root@localhost simple_merge]# ls -lah dist/
total 364K
drwxr-xr-x 2 root root   23 Mar 26 20:13 .
drwxr-xr-x 5 root root   88 Mar 26 20:13 ..
-rw-r--r-- 1 root root 364K Mar 26 20:13 bundle.js

首先gulp.src框定了读取src目录下的所有文件名后缀为.js的文件,并通过.pipe属性方法将数据流传递给concat插件,而concat运行时根据制定的文件生成名称(bundle.js)将多个文件对象逐一进行读取以及写入到该制定的文件生成名称的对象中,并通过this关键字写入到当前实例,最终gulp.dest会根据标准接口去完成写入的行为(创建目录、写入文件)。

理解数据流转发过程(through2)
上面这个例子从代码层面来看,就一行有效代码,但是从文字描述来看可能过于复杂和带有不确定性,所以我这里将采用through2来打印一些日志来观察它的运行原理和过程(请注意:这个例子并没有做文件合并。);其实通过查看gulp-concat插件的源代码就可以发现它也是采用through2来完成文件对象的获取。

# 创建一个案例目录
[root@localhost ~]# mkdir -p simple_pipeline/src
[root@localhost ~]# cd simple_pipeline/

# 安装gulp和react
[root@localhost simple_pipeline]# cnpm install gulp vue react through2 --save-dev

# 将react.js和vue复制到src目录
[root@localhost simple_pipeline]# cp node_modules/react/dist/react.js node_modules/vue/dist/vue.js src/

# 撰写gulpfile.js文件
[root@localhost simple_merge]# vim gulpfile.js
var gulp = require('gulp'),
    through = require('through2')

gulp.task('displayDetails', function() {
    return gulp.src('src/*.js')
           .pipe(through.obj(function(file, encode, callback) {
               console.log(file);
               console.log(encode);
               console.log(callback);
               callback();
           }))
           .pipe(gulp.dest('dist/'))
})

# 观察运行过程
[root@localhost simple_gulppipe]# ./node_modules/gulp/bin/gulp.js displayDetails
[20:39:24] Using gulpfile ~/fron_end/simple_gulppipe/gulpfile.js
[20:39:24] Starting 'displayDetails'...


<File "react.js" <Buffer 20 2f 2a 2a 0a 20 20 2a 20 52 65 61 63 74 20 76 31 35 2e 34 2e 32 0a 20 20 2a 2f 0a 28 66 75 6e 63 74 69 6f 6e 28 66 29 7b 69 66 28 74 79 70 65 6f 66 ... >>
utf8
[Function]


<File "vue.js" <Buffer 2f 2a 21 0a 20 2a 20 56 75 65 2e 6a 73 20 76 32 2e 32 2e 35 0a 20 2a 20 28 63 29 20 32 30 31 34 2d 32 30 31 37 20 45 76 61 6e 20 59 6f 75 0a 20 2a 20 ... >>
utf8
[Function]


[20:39:24] Finished 'displayDetails' after 55 ms

Gulp.src

语法:
gulp.src(globs[, options])
根据提供的参数来读取文件源,并返回一个基于Vinyl风格的文件对象(流数据),这种文件对象可以通过pipe管道以一个文件对象传递给其他程序继续完成整合的行为。

globs
支持两种类型的数据,分别是字符串(glob)和列表(array of globs)。

glob支持字符串形式以通配符的方式来匹配文件集合。

// src/*.js标识匹配src目录下的所有后缀名为.js的文件,
// 并将它们逐一转换成Vinyl风格的文件对象。
gulp.src('src/*.js')   

array of globs支持列表形式以通配符的方式来匹配文件集合。

gulp.src(['src/*.js', 'server/*.js', 'client/*.js'])

options
options选项是可选的,因为程序默认会给它赋值,除非有特定需求,否则一般不需要配置options;默认情况下程序会这样在程序内部帮你实现赋值。

gulp.src('src/*.js', { buffer: true, read: true, base: null })

还有另外一个options要单独进行处理(那就是base),默认情况下base是一个null的值(也可以在glob处通配符'**'或指定一个明确的指),意思是说,当所有程序处理完之后,最终交付给gulp.dest生成文件时,是否在指定的目录下生成有子目录结构的存放;例如:
样例1: 通配符

# 查看目录结构
[root@localhost simple_gulpsrc]# ls 
node_modules    package.json    src
[root@localhost simple_gulpsrc]# tree src
src
└── client
    └── js
        ├── jianshu
        │   ├── react-with-addons.js
        │   ├── react-with-addons.min.js
        │   ├── react.js
        │   └── react.min.js
        └── youdao
            ├── vue.common.js
            ├── vue.common.min.js
            ├── vue.esm.js
            ├── vue.js
            ├── vue.min.js
            ├── vue.runtime.common.js
            ├── vue.runtime.esm.js
            ├── vue.runtime.js
            └── vue.runtime.min.js

# 创建通配符版本gulpfile_wildcard.js
[root@localhost simple_gulpsrc]# vim gulpfile_wildcard.js
var gulp = require('gulp')

gulp.task('build', functioin () {
    return gulp.src('src/client/js/**/*.js')
           .pipe(gulp.dest('dist'))
})

# 生成目标文件
[root@localhost simple_gulpsrc]# ./node_modules/gulp/bin/gulp.js --gulpfile gulpfile_wildcard.js build
[10:40:13] Using gulpfile ~/zhengtong/gulp_srcbase/gulpfile_wildcard.js
[10:40:13] Starting 'build'...
[10:40:13] Finished 'build' after 72 ms

# 查看目标目录
[root@localhost simple_gulpsrc]# tree dist
dist
├── jianshu
│   ├── react-with-addons.js
│   ├── react-with-addons.min.js
│   ├── react.js
│   └── react.min.js
└── youdao
    ├── vue.common.js
    ├── vue.common.min.js
    ├── vue.esm.js
    ├── vue.js
    ├── vue.min.js
    ├── vue.runtime.common.js
    ├── vue.runtime.esm.js
    ├── vue.runtime.js
    └── vue.runtime.min.js

样例2:通配符 + base

# 删除dist目录
[root@localhost simple_gulpsrc]# rm -rf dist/

# 创建通配符+base版本的gulpfile_wildcardBase.js
[root@localhost simple_gulpsrc]# vim gulpfile_wildcardBase.js
var gulp = require('gulp')

gulp.task('build', function () {
    return gulp.src('src/client/js/**/*.js', {base: 'src'})
           .pipe(gulp.dest('dist'))
})

# 生成目标文件
[root@localhost simple_gulpsrc]# ./node_modules/gulp/bin/gulp.js --gulpfile gulpfile_wildcardBase.js build
[10:45:18] Using gulpfile ~/zhengtong/gulp_srcbase/gulpfile_wildcardBase.js
[10:45:18] Starting 'build'...
[10:45:18] Finished 'build' after 65 ms

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

推荐阅读更多精彩内容