小鱼二
安装 nrm https://github.com/Pana/nrm
确保Gulp是4.0版本
下载这个项目 https://github.com/xiaoyu2er/automating-your-workflow-with-gulp
// 安装 node 4
$ nvm install 4
$ nvm use 4 // 使用 node v4
$ nvm alias default 4 // 默认是 v4, 下次打开terminal还是4
// 安装nrm
$ npm install -g nrm
$ nrm ls
$ nrm use cnpm // 选择淘宝镜像 cnpm
// 删除之前安装过的 gulp命令行工具
$ npm uninstall -g gulp
// 安装最新的gulp命令行工具
$ npm install -g gulpjs/gulp-cli#4.0
// 下载这个练手项目
$ git clone git@github.com:xiaoyu2er/automating-your-workflow-with-gulp.git
$ cd automating-your-workflow-with-gulp
$ npm install
视频 JavaScript Build Automation With Gulp http://pan.baidu.com/s/1i56ObbB
Gulp 4 入门指南(https://github.com/baixing/FE-Blog/issues/7)
Automate and enhance your workflow
不仅仅是自动化的构建工具
懒
自动化构建
提升代码质量
好钢用在刀刃上 (专注于代码)
早下班
升职加薪
…
编译
sass, less -> css
vendor-prefix
es6, typeScript, coffee -> js
压缩 (css, 图片, 雪碧图, 图标SVG)
混淆 (uglify)
sourcemaps
立即执行函数
Angular(templateCache, 依赖注入)
HTML生成 引用的注入(css,js)
文件重命名
全局文本的替换
版本号 文件hash;
测试
删除文件
文档自动生成
自动上传, 部署
git commit hook (commit记录的格式化)
其他:
生成的文件多大?
生成的文件版本号汇总?
开发阶段出错系统提示?
上述的一切 都可以使用Gulp自动化完成
而且可以快的让你飞起来!
Automate and enhance your workflow
work smarter, not harder
Gulp是基于代码的, Grunt是基于配置的
Gulp是基于流的, Grunt是基于文件的
基于代码可以借助node模块, 更加灵活
更加简洁
更好的debug
快 [微笑]
在Gulp4.0之前, Gulp一共只有4个API:
Gulp4.0不向下兼容, 共8个API
经笔者实践, Gulp4.0的API简化了任务间的依赖关系
思维复杂度降低
因此
我会按照Gulp4.0的API进行讲解
注意 Gulp 4.0 尚未正式发布
所以在项目中安装依赖的时候, 写法稍微有点不同:
// name: gulp任务的名字, 如果不提供, 将用 fn.name 或者 fn.displayName 来作为任务的名字
// fn: 异步函数; fn 可以接收一个callback, 在异步操作结束后调用;
// 或者 fn可以返回一个 promise, stream, child process, RxJS observable 以示任务结束
// fn.name, fn.displayName. 由于fn.name不可修改,
// 针对匿名函数可以提供一个 displayName属性来充当任务的名称
// fn.description 使用 gulp --tasks 时, 此字段会出现在task的名字后面
//
gulp.task('task', function someTask(done) {
// 1. done(); 后续举例
// 2. return a promise; 后续举例
// 3. return stream; 后续举例
// 4. return child process; 未研究
// 5. return RxJs observable; 未研究
});
function taskName() {}
gulp.task(taskName);
$ gulp hello
[19:37:48] Using gulpfile ~/Tech/workspace/github/automating-your-workflow-with-gulp/demo/gulpfile.js
[19:37:48] Starting 'hello'...
hello
[19:37:48] Finished 'hello' after 1.89 ms
var gulp = require('gulp');
gulp.task('hello', function (done) {
console.log('hello');
done(); // 显示的调用回调函数表示任务完成; 尝试将这里去掉
});
var del = require('del');
/**
* 删除build目录下的所有文件
*/
gulp.task('clean', function () {
// del操作是一个promise
return del(config.buildDir);
});
// globs: String or Array
// 表示输入文件的通配符, 可以是字符串, 也可以是字符串数组
// 如 gulp.src(['*.js', '!b*.js', 'bad.js'])
gulp.src('globs', {
// cwd, 表示 blobs 的当前目录, 很有用哦!
// Default: process.cwd()
cwd: '',
// base, 表示输入文件的基准地址;
// 默认是第一个通配符前的地址 如: gulp.src('client/js/**/*.js') base 就是 client/js/
// 在保证输出目录结构的时候有用, 后续会讲解
base: '',
// buffer表示文件在内存中的存储形式, 默认是true,
// 如果是false, 那么返回的文件形式将是 file.contents, 大型文件有用, 原理未研究.
buffer: true,
// 文件最后修改时间小于这个值得将会忽略掉
// 这里可以使用 gulp.lastRun, 后续会讲解.
since: 'Date or Number',
// 允许空文件, 否则src不存在的时候会报错
allowEmpty: false,
// 是否真正读取文件, 如果为false, 只有文件的meta信息会被读取, 后续会举例
read: true,
passthrough: false // 没研究
});
gulp.src(glob, options) 中的option 还有其他选项, 详细请看:
https://github.com/gulpjs/glob-stream#options
https://github.com/isaacs/node-glob#options
gulp.src('')
// path: String or a function(file) (可以是个函数欧!)
// 输出文件的目录
.pipe(gulp.dest('path', {
// cwd, 当前目录, 只有path是相对路径的时候才会用到
cwd: 'process.cwd()',
// mode, 输出文件的mode,
// 默认和源文件一致 或者 和process的mode一致; 如: "0744", 0744 or 484
mode: 'String or Number',
// dirMode, 输出文件夹的mode
// 默认是process的mode
dirMode: 'String or Number',
// overwrite, 是否覆盖已经存在的文件
overwrite: true
}))
/**
* 拷贝.css文件到build目录下
*/
gulp.task('css', function () {
// 这里的cwd参数表示css/目录的父级目录;
// 这里的base参数, 是为了保证源目录和生成目录的目录结构一致;
// 可以尝试删除看看有何异同 // 你会发现目录结构被破坏掉了!
return gulp.src('css/**/*.css', {cwd: 'src', base: 'src'})
.pipe(gulp.dest(config.buildDir));
});
gulp.task('one', function (done) {
done();
});
function two(done) {
done();
}
gulp.task('three', function (done) {
done();
});
function four(done) {
done();
}
gulp.task('five', function (done) {
done();
});
gulp.task('series¶llel', gulp.parallel(
'one',
gulp.series(two, 'three'),
gulp.parallel(four, 'five')
));
与 gulp.dest 功能一致, 只不过是生成软连接
// folder: String or Function(file)
.pipe(gulp.symlink('folder', {
cwd: 'process.cwd()', // 只有path是相对路径的时候才会用到
dirMode: 'String or Number' // 默认是process的mode
}))
// glob: String or Array;
var watcher = gulp.watch('glob', {
ignored: 'glob', // 忽略的文件
usePolling: false, // 一般用于网络文件或者虚拟机里的文件
cwd: '', // glob的base路径
alwaysStat: false // 如果需要 fs.Stats 的所有事件可以设置为true, 稍微影响性能
}, function () {
// do something here
});
// gulp.watch 返回一个 FSWatcher; 可以接收 add, change, unlink 事件
// 函数参数:
// path: 文件的路径, 如果上述opts.cwd指定, path为相对路径
// stats: 一个 fileStat 对象, 可能会被提供; 如果opts.alwaysStat == true, 那么stats一定会被提供;
watcher.on('add|change|unlink|', function (path, stats) {
console.log('File ' + path + ' was added|changed|removed');
});
// watcher的一些方法
watcher.close(); // 关闭文件监听
watcher.add('glob'); // 继续添加监听文件
watcher.unwatch('glob'); // 不再监听glob所代表的文件, 其余继续
var del = require('del');
gulp.task('watch', function () {
var watcher = gulp.watch('css/**/*.css', {cwd: 'src'},
gulp.series('build:css', 'build:inject'));
watcher.on('add', (filePath) => console.log('add', filePath));
watcher.on('change', (filePath) => console.log('change', filePath));
// 当文件删除的时候, 同时删除目标目录下的文件, 这样保证 build:inject 的时候不会引入已经删除的文件
watcher.on('unlink', (filePath) => {
console.log('delete', filePath);
var src = path.relative(path.resolve('src'), filePath);
var dest = path.resolve(config.buildDir, src);
return del(dest);
});
});
├── gulpfile.js
├── build/ 生产目录
└── src/ 源文件目录
├── css
│ ├── add.scss
│ ├── delete.scss
│ ├── main.scss
│ └── normalize.css
├── img
│ └── gulp.png
├── index.html
├── js
│ ├── app.js
│ ├── controllers
│ │ ├── add.controller.js
│ │ └── delete.controller.js
│ ├── directives
│ │ ├── add.directive.js
│ │ └── delete.directive.js
│ ├── filters
│ │ ├── lowerCase.js
│ │ └── upperCase.js
│ └── services
│ └── counter.js
├── lib
│ └── angular.js
└── views
├── add.tpl.html
└── delete.tpl.html
var gulp = require('gulp');
var del = require('del');
var inject = require('gulp-inject');
var order = require("gulp-order");
var cleanCSS = require('gulp-clean-css');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var size = require('gulp-size');
var rev = require('gulp-rev');
var htmlmin = require('gulp-htmlmin');
var cached = require('gulp-cached');
var sass = require('gulp-sass');
var iife = require('gulp-iife');
var print = require('gulp-print');
var eventStream = require('event-stream');
var ngAnnotate = require('gulp-ng-annotate');
var ngTemplates = require('gulp-ng-templates');
小鱼二