您的位置:首页 > 其它

gulp

2015-11-09 20:25 459 查看


gulp


一、前言

gulp是一个适用于javascript的构建工具,能自动执行已定义的常见任务,如语法检测(jshint)、测试(mocha)、压缩(uglify)等。其相当于maven之于java。

还有一个更早出现的构建工具grunt,其也提供了gulp的功能,且功能更为强大,但其在配置及使用上更为繁琐,其实现的理念也导致其编译效率较低,新出现gulp的出现正是为了解决这些问题,在后面的使用过程中将逐渐对比两者的优劣。

官网: http://gulpjs.com/

中文:http://www.gulpjs.com.cn/


二、安装

npm install -g gulp


gulp提供的是一个构建工具,要真正实现我们需要的功能,还需要下载相关的插件,如
npm install gulp-uglify --save-dev


三、使用API:

下面通过实现一个gulp的demo,来学习其API。

创建gulp文件夹,新建gulpfile.js作为gulp的启动文件,插入如下代码
var gulp = require('gulp');

gulp.task( 'default', function(){
console.log( 'this is gulp default' );
});


使用cli进入到 gulp目录,执行gulp,其会自动找到gulpfile.js并执行,打印信息如下
cc@cc:~/Work/gulp$ gulp
[07:23:15] Using gulpfile ~/Work/gulp/gulpfile.js
[07:23:15] Starting 'default'...
this is gulp default
[07:23:15] Finished 'default' after 133 μs


执行完后会自动退出,后面会有不自动退出的情况,μs是微秒单位

现在我们按一个较正规的系统目录,参照前面几章实现的项目。

cli到gulp目录下,执行 npm init,自行配置相关描述,可如下
{
"name": "gulp",
"version": "1.0.0",
"description": "this is a demo for gulp",
"main": "index.js",
"dependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "upopen.cn",
"license": "ISC"
}


gulp下新建assets/core/js/base.js,插入
function base( name ){
console.log( 'this is base, hi ' + name );
}


再新建assets/core/css/common.css,插入
body{
margin: 0;
padding: 0;
background: #afafaf;
}
a{
text-decoration: none;
}


下载基于uglify的代码压缩插件 gulp-uglify

cli执行 npm install gulp-uglify --save-dev
修改gulpfile.js
var gulp = require( 'gulp' ),
uglify = require( 'gulp-uglify' );

gulp.task( 'default', function(){
gulp.src( 'assets/core/js/base.js' )
.pipe( uglify() )
.pipe( gulp.dest( 'assets_min' ) );
});


cli执行gulp

即实现了将assets/core/js/base.js压缩并插入到新建文件夹 assets_min内,和nodejs写法很相同,且条目简单,若用grunt做同样的功能则需要做相当多的配置。

gulp的API总共有四个,我们一次就用到了其中的三个。

gulp.task( name[, deps], fn ):创建一个任务

name: String 任务名 deps: Array 任务依赖,其会在任务之前执行 fn: Function 任务事件

cli执行gulp时,默认会执行gulpfile.js里的default任务,若需执行其它任务,可以将其它任务作为default的deps,如
var gulp = require( 'gulp' ),
uglify = require( 'gulp-uglify' );

gulp.task( 'default', [ 'minify' ] );
gulp.task( 'minify', function(){
gulp.src( 'assets/core/js/base.js' )
.pipe( uglify() )
.pipe( gulp.dest( 'assets_min' ) );
});


若只是想单独执行minify,也可以通过cli执行 gulp minify,来显示执行指定的task

fn函数内的常见形式是 gulp.src( 'assets/core/js/base.js' ).pipe( uglify() ),读取文件.pipe( 执行压缩 ).pipe( 添加到文件夹 ),pipe是用流传递操作后的数据,下一个pipe接收到数据做操作后再向后传递,比起grunt的创建临时文件效率更高。可以通过输出src的引用查看
var stream = gulp.src( ... ).pipe( .. )
console.log( stream );


文件流的工作原理 https://github.com/substack/stream-handbook

fn 也支持异步的形式,需要在function添加实参cb,当异步返回时执行cb()即可,和mocha的回调添加实参done同理,如
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
exec('jekyll build', function(err) {
if (err) return cb(err);
cb();
});
});


注意task默认将以最大的并发数执行,多个task之间不会相互等待,若需序列执行,注意使用deps 及 异步情况

gulp.src( globs[, options ] )

读取指定路径的文件,输出到piped的下一个插件中。

globs的语法 https://github.com/isaacs/node-glob

globs可以为Array / String,如上例中,可以是
'assets/core/js/base.js'
'asserts/*/*/base.js'
'asserts/*/*.js'
[ 'assets/*/*.js' ]


更多匹配规则可以参考 https://github.com/isaacs/minimatch

注意 * 的用法,/*.js,表示当前子目录的所有js文件,而/*/*.js,其N级下的子目录,即当有多层子目录时,不需要添加多层的*

options可以配置
buffer: true | false  是否以流的形式传播
read: true | false     是否可读
base: ''


其中只base作为统一路径可能被使用外,其它两个基本不会使用,后面会用到base

gulp.dest( path[, options ] )

将接收到的数据输出到path下,若path不存在,会自动创建
path: String | Function,可据fun生成路径
options: 几乎不用
cwd: String 输出当前路径
mode: 0777,用于配置权限


注:需要注意path的使用,其和gulp.src里的glob及 options里的base设置是相关,

注意上例中以下几种情况
gulp.src( 'assets/core/js/base.js' ).pipe( gulp.dest( 'assets_min' ) ); //assets_min/base.js
gulp.src( 'assets/core/**/base.js' ).pipe( gulp.dest( 'assets_min' ) ); //assets_min/js/base.js
gulp.src( 'assets/**/**/base.js' ).pipe( gulp.dest( 'assets_min' ) ); //assets_min/core/js/base.js
gulp.src( 'assets/core/**/base.js',{base: 'assets'}).pipe( gulp.dest( 'assets_min' ) ); //assets_min/core/js/base.js


可以看出path取的是 **部分,若设置了base,则取base后的部分。

实现一个更复杂些的例子来表现gulp的用法。

在assets/core/js/ 下与base.js同级新建common.js

新增语法检测插件jshint,及文件组合插件concat。

cli下执行 cnpm install gulp-jshint gulp-concat --save-dev

修改gulpfile.js
var gulp = require( 'gulp' ),
uglify = require( 'gulp-uglify' ),
jshint = require( 'gulp-jshint' ),
concat = require( 'gulp-concat' );

gulp.task( 'default', function(){
gulp.src( 'assets/core/**/**.js',{ base: 'assets' } )
.pipe( jshint() )
.pipe( uglify() )
.pipe( concat( 'all.js' ) )
.pipe( gulp.dest( function(){ return 'assets_min' } ) )
});


读取assets/core/js下的base.js、common.js --> jshint语法检测 --> uglify压缩 --> concat合并为all.js --> 添加到 assets_min 文件夹下

再讲下gulp的第四个API

gulp.watch( glob[, options ], task );

gulp.watch( glob[, options ], cb );
glob: String | Array  监听文件的路径
options:
tasks: Array 当被监听的文件变动时,需要执行task
cb: function 当文件变化时可执行的函数,


在gulpfile.js文件里追加
gulp.watch( 'assets/**/**.js',  [ 'default' ] );
gulp.watch( 'assets/**/**.js', function( event ){
console.log( event );
})


cli重新执行gulp,相比之前可以看到cli下并没有自动退出,此时修改assets/core/js/base.js保存后,cli自动显示执行了default,并且输出了{ type: 'changed',path: '/home/cc/Work/gulp/assets/core/js/common.js' },即event表示文件的操作type及path。 打开assets_min下的all.js,可以看到修改后的内容也已经添加进来了。

gulp.watch本身会返回一个实例

其提供了events( change | end | error | ready | nomatch ) 及 method ( end | files | add | remove )

上面为watch追加的代码,可以修改为
var watcher =gulp.watch( 'assets/**/**.js', [ 'default' ] );
watcher.on( 'change', function( event ){
console.log( event );
});


可以达到同样的效果

四、插件Plugin

gulp作为一个构建工具,其只是提供了一个平台,可运行各款插件,以达到我们的项目需求,所以当我们学会使用gulp后,还需要了解其提供了哪些插件,甚至对没有提供的插件,我们可以自行封装。

插件列表 http://gulpjs.com/plugins/

常用的插件有
压缩CSS(gulp-minify-css)
语法检查(gulp-jshint)
文件拼接(gulp-concat)
文件压缩(gulp-uglify)
图片压缩(gulp-imagemin)
实时加载(gulp-livereload)
文件清理(gulp-clean)
更新通知(gulp-notify)
图片快取(gulp-cache)
Autoprefixer(gulp-autoprefixer)


当需要引用的插件列表较多时,可以使用gulp-load-plugins模块,代替所有插件的require,于是前面demo也可以写成
var gulp = require( 'gulp' ),
plugins = require( 'gulp-load-plugins' )();

gulp.task( 'default', function(){
gulp.src( 'assets/core/**/**.js',{ base: 'assets' } )
.pipe( plugins.jshint() )
.pipe( plugins.uglify() )
.pipe( plugins.concat( 'all.js' ) )
.pipe( gulp.dest( function(){ return 'assets_min' } ) );
});


注意各插件的命名。

五、browser-sync

再介绍一个很酷的功能browser-sync。

当我们修改html/css/js等静态资源文件时,需要刷新才能看到效果,如果做测试时填写了一堆表单,还需要重新来做,browser-sync就提供这样的功能。不过其目前只在修改css文件时做到单独加载,Html/Js 的自动刷新还是全页面的。

cli上执行 npm install browser-sync --save-dev

在当前demo下新建views/index.html,引入上例中的 css / js,如下
<!DOCTYPE html>
<html>
<head>
<link href="../assets/core/css/common.css" type="text/css" rel="stylesheet" />
</head>
<body>
this is a demo for browser-sync
<input type="text" />
<script src="../assets/core/js/common.js"></script>
</body>
</html>


在gulpfile.js后追加代码
...
var browserSync = require( 'browser-sync' );
...
gulp.task( 'browser-sync', function(){
var files = [ 'views/*.html', 'assets/**/*.js', 'assets/**/*.css' ];
browserSync.init( files, {
server: { baseDir: '' }
})
})


启动gulp,提示
cc@cc:~/Work/gulp$ gulp
[16:02:41] Using gulpfile ~/Work/gulp/gulpfile.js
[16:02:41] Starting 'browser-sync'...
[16:02:41] Finished 'browser-sync' after 35 ms
[16:02:41] Starting 'default'...
[16:02:41] Finished 'default' after 310 ms
[BS] Access URLs:
-------------------------------------
Local: http://localhost:3000 External: http://172.16.22.29:3000 -------------------------------------
UI: http://localhost:3001 UI External: http://172.16.22.29:3001 -------------------------------------
[BS] Serving files from: ./
[BS] Watching files...


浏览器自动打开 localhost:3000,显示cannot get /,补全网址 localhost:3000/views/index.html,即打开了前面定义的html,此时对该html及引用的common.js /common.css的任何保存操作,都会导致资源自动更新,其中css的修改,只会更新当前资源,不会导致页面的整体刷新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: