Gulp
流式构建工具
微博: frontnode
QQ: 2080432723
开源地址: github.com/frontnode
Web开发,流程改进,最佳实践,性能优化
流
你的应用不是一个大车间,而是由一系列的管道打通的
我们应该有如同使用橡胶软管的方法来连接程序——当需要通过不同的方式来操作数据的时候能够将另外的片段连接进来。这也是IO的方式.- Doug McIlroy
最早流的概念是在UNIX里提出来的并且历经多年的实践验证证明这是一种可靠的方式。这也顺应了UNIX的设计思路,每个组件只做一件事情,并且将这件事情做好,大型的系统是由这些小的可靠的组件来组成。
你可以将一个流的输出作为另一个流的输入并且使用库来抽象地操纵流以描述高层次的流程控制。- substack
程序员都知道流程控制
阅读substack关于流的简明概览
学习新的流程控制技术让你更加高效
为什么是流?
在头脑中描绘一个构建系统的样子。
(它需要读入文件,修改它们并且输出新的文件)
你可能是这样想的

绝不是这样的

糟糕的情况是怎样的?
- 一个插件做了过多的事情
- 只是想使用javascript压缩器,需要先回答是不是要添加banner
- 插件做了不该插件做的事情
- 想要运行测试?装个插件吧
- 当你想做很多事情的时候config的格式看起来就是一坨...
- 不是按照node的方式来书写的
- 由于不良的流程控制导致一堆头疼的临时文件和目录
你的构建系统应该助力而不是阻碍你的工作
它应该仅仅操纵文件,让其他的库来处理其他的问题
Gruntfile例子
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';'
},
dist: {
src: ['src/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
qunit: {
files: ['test/**/*.html']
},
jshint: {
files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
// options here to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint', 'qunit']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('test', ['jshint', 'qunit']);
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
};
-
代码静态检查
-
运行测试
-
合并JS
-
压缩文件
-
如果文件改动了重新执行上面的步骤
切换工具

Gulpfile 例子
var gulp = require('gulp');
var pkg = require('./package.json');
var concat = require('gulp-concat');
var minify = require('gulp-minify');
var jshint = require('gulp-jshint');
var spawn = require('child_process').spawn;
var scriptFiles = './src/**/*.js';
gulp.task('compile', function(){
// concat all scripts, minify, and output
gulp.src(scriptFiles)
.pipe(concat({fileName: pkg.name+".js"})
.pipe(minify())
.pipe(gulp.dest('./dist/'));
});
gulp.task('test', function(){
// lint our scripts
gulp.src(scriptFiles).pipe(jshint());
// run our tests
spawn('npm', ['test'], {stdio: 'inherit'});
});
gulp.task('default', function(){
gulp.run('test', 'compile');
gulp.watch(scriptFiles, function(){
gulp.run('test', 'compile');
});
});
-
代码静态检查
-
运行测试
-
合并JS
-
压缩文件
-
如果文件改动了重新执行上面的步骤
有啥不一样的?
- 用 Gulp 后你的构建文件看起来是程序而不是配置
- 十分易于上手,核心API只有4个
- 你可以使用nodejs或者javascript的标准库和方法来做事情
- 单一责任原则,插件很简单并且只做一件事情——最多是个20行的方法
- 任务以最大并发来执行
- I/O 以你想象中的方式工作,基于流,而不是生成很多临时文件(像grunt的方法一样)
安装
添加命令行工具
npm install -g gulp 添加项目开发依赖
cd project
npm install gulp --save-dev
编写代码
var gulp = require('gulp');
gulp.task('default', function () {
console.log('welcome to gulp');
});
运行一把
gulp 就是这么简单
跟grunt差不多?
Gulp 仅仅是提供了一些流和基本的任务系统
我们来看看gulp的API,只有4个
gulp.task(name, fn)
给任务起个名字。
你也可以指定一些依赖如果其他任务需要首先运行。
gulp.watch(glob, fn)
监视文件变化并且运行相应的任务
在code中可以方便的调用
gulp.src(glob)
返回可读文件流。
获取文件系统 glob (如同grunt一样) 并且开始返回匹配的文件.
其他的流会把src作为源一级一级连接
gulp.dest(folder)
返回可写文件流
使用管道串联的文件对象被保存到文件系统
插件开发说明
祝贺
你已经是一个Gulp专家啦
如何创建你自己的插件参考README文件
其他的构建工具
-
基于文件的FEZ
- Alloy Team modjs
- FEX FIS
- Make
- Ant
Questions?
Get started with gulp
By frontnode
Get started with gulp
Streaming build systems
- 1,552
