目录javascript
gulp是前端开发过程当中对代码进行构建的工具,是自动化项目的构建利器;她不只能对网站资源进行优化,并且在开发过程当中不少重复的任务可以使用正确的工具自动完成;使用她,咱们不只能够很愉快的编写代码,并且大大提升咱们的工做效率。css
gulp是基于Nodejs的自动任务运行器, 她能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤。在实现上,她借鉴了Unix操做系统的管道(pipe)思想,前一级的输出,直接变成后一级的输入,使得在操做上很是简单。经过本文,咱们将学习如何使用Gulp来改变开发流程,从而使开发更加快速高效。html
参考文章 http://www.cnblogs.com/roddy/p/6524252.html前端
$ npm install gulp -g
java
查看是否正确安装。node
$ gulp -v
git
出现版本号表示安装成功。github
咱们新建一个项目文件夹"gulp",而后定位到"gulp"文件中npm
$ cd gulp
json
在安装项目依赖包gulp以前,咱们先来看看package.json文件。
package.json是每一个基于Nodejs项目必不可少的配置文件,其中包括项目名称、版本号和所须要的依赖包列表等信息,它是存放在项目根目录中的json文件。
想像一下,若是把项目比做是餐厅中一道菜的话,项目中使用到的依赖包就是这道菜的食材,而package.json文件就是这道菜的食材列表,那么package.json存在的做用是什么?我想最主要的做用就是方便管理项目,用过github童鞋都知道,多人协同工做的时候常常会使用pull和push,因为package.json存在,咱们就不须要对项目依赖归入版本管理,只须要管理package.json就好了,而后根据package.json本地构建项目依赖。
基于命令行建立package.json文件
$ npm init
而后根据提示输入。
package.json基本格式(注意:实际json文件中是不容许出现注释的!)
{ "name": "gulp", //项目名称(必须) "version": "1.0.0", //项目版本(必须) "description": "This is gulp project !", //项目描述(必须) "homepage": "", //项目主页 "repository": { //项目资源库 "type": "git", "url": "" }, "author": { //项目做者信息 "name": "roddy", "email": "xxxxx@.com" }, "license": "ISC", //项目许可协议 "devDependencies": { //项目依赖列表 "gulp": "^3.8.11" } }
固然,你也能够直接在项目根目录中建立package.json文件,而后复制上面配置代码进去。OK! 如今"gulp"项目中只有一个"package.json"文件,那么咱们要怎么安装项目依赖包gulp呢?其实咱们"package.json"中"devDependencies"字段已经列出了"gulp"包,咱们只须要根据"package.json"来安装依赖就能够了,或者用npm来安装依赖。
$ npm install
$ npm install gulp --save-dev
细心的你会发现,咱们前面已经全局安装过了gulp,这里为何还要项目安装一次gulp?全局安装gulp是让咱们能使用gulp命令行,项目安装gulp是让项目能引用gulp模块!
gulpfile.js为gulp项目的配置文件也是咱们的任务文件,咱们使用gulp对文件进行压缩、打包这些任务就是写在gulpfile.js文件中。
咱们在"gulp"项目根目录中建立一个js文件"gulp.js",代码以下:
// 引入依赖gulp var gulp = require( 'gulp' ); // 建立一个'default'任务 gulp.task( 'default', function() { // 将你的默认的任务代码放在这 } );
用全局gulp来运行gulpfile.js中的任务(全局安装gulp才能使用gulp命令,若是没有全局安装,这里会报错!)
$ gulp
或者执行指定的任务。
$ gulp <taskname>
默认的名为"default"的任务(task)将会被运行,在这里,这个任务并未作任何事情。
好了,了解gulp大体的工做步骤后,有必要咱们来学习下gulp中的API,这样你才能根据本身需求写gulpfile.js。
建立一个gulp任务。
name
: [String] 任务名称,中间不要有空格。
deps
: [Array] 一个包含任务列表的数组,这些任务会在你当前任务运行以前完成。
fn
: [Function] 任务的回调函数,任务具体代码。
gulp.task( "taskname", [ "task1", "task2", ... ], function() { // 将你的任务代码放在这 } );
监视文件,而且能够在文件发生改动时候作一些事情。它总会返回一个EventEmitter来发射(emit)事件。
glob
: [String/Array] 监视的文件路径或者文件路径数组。
opts
: [Object] 传给依赖包gaze
的参数。
tasks
: [Array] 须要在文件变更后执行的一个或者多个经过 gulp.task() 建立的 task 的名字。
gulp.task( "task1", function() { console.log( "gulp" ) } ); gulp.task( "default", function() { gulp.watch( "xx.js", [ "task1" ] ); } );
监视文件,而且能够在文件发生改动时候作一些事情。它总会返回一个EventEmitter来发射(emit)事件。
glob
: [String|Array] 监视的文件路径或者文件路径数组。
opts
: [Object] 传给依赖包gaze
的参数。
cb
: [Function] 每次变更须要执行的回调函数,该函数被传入一个事件对象event。
├─event.type
: [String] 变更类型,"added"、"changed"、"deleted"。
└─event.path
: [String] 触发该事件的文件路径。
gulp.task( "default", function() { gulp.watch( "xx.js", function( event ) { console.log( event.path + "is" + event.type ); } ); }
匹配要处理的源文件路径,而且返回一个stream它能够被piped到别的插件中。
globs
: [String|Array] 匹配glob模式的文件路径或者文件路径数组。
├─*
: 匹配任意文件名。 例:src/*.js
<=>src中全部js文件
。
├─**
: 匹配0个或多个文件夹。 例:src/**/*.js
<=>src中0个或多个文件夹中的js文件
。
├─{}
: 匹配多个属性。 例:src/*.{js,css,html}
<=>src中全部js,css,html文件
。
└─!
: 排除文件。 例:!src/a.js
<=>不包含src中的a文件
。
options
: [Object] 三个可选配置
├─options.buffer
: [Boolean] 默认true
,设置为false,将返回file.content的流而且不缓冲文件,处理大文件时很是有用。
├─options.read
: [Boolean] 默认true
,设置false,将不执行读取文件操做,返回null。
└─options.base
: [String] 默认 glob通配符以前的路径,最后替换掉base来获得输出文件路径。
假如咱们src目录中有一个文件夹js,其中有一个test.js文件
gulp.task( "default", function() { // 匹配文件"src/js/test.js", 而且把options.base解析为"src/js" gulp.src( "src/js/*.js" ) // 用"dist"替换掉base路径,并写入该文件"dist/test.js" .pipe( gulp.dest( "dist" ) ); } ); gulp.task( "task1", function() { // 匹配文件"src/js/test.js", 而且把options.base设置为"src" gulp.src( "src/js/*.js", { base : "src" } ) // 用"dist"替换掉base路径,并写入该文件"dist/js/test.js" .pipe( gulp.dest( "dist" ) ); } );
能被 pipe 进来,而且将会写文件。而且从新输出(emits)全部数据,所以你能够将它 pipe 到多个文件夹。若是某文件夹不存在,将会自动建立它。
path
: [String|Function] 文件将被写入的路径(输出目录)。也能够传入一个函数,在函数中返回相应路径。
options
: [Object] 两个可选配置。
├─options.cwd
: [String] 默认"options.cwd()"
,输出目录的 cwd 参数,只在所给的输出目录是相对路径时候有效。
└─options.mode
: [String] 默认"0777"
,八进制权限字符,用以定义全部在输出目录中所建立的目录的权限。
前面介绍了"gulp"怎么安装使用以及"gulp"的API,可是"gulp"究竟是怎么样对文件进行压缩、合并等操做的呢?其实"gulp"要完成这些操做,靠的就是基于它的一些功能插件,利用这些插件来对文件进行操做,下面咱们就介绍几种经常使用的插件。
插件 : gulp-clean-css
Github : https://github.com/jakubpawlowicz/clean-css
$ npm install gulp-clean-css --save-dev
建立gulpfile.js
var gulp = require( 'gulp' ); var cleanCss = require( 'gulp-clean-css' ); gulp.task( "default", function() { // 读取"src"中的全部css文件 return gulp.src( "src/*.css" ) // 压缩css文件 .pipe( cleanCss() ) // 写入"dist"文件夹中 .pipe( gulp.dest( "dist" ) ); } );
运行gulpfile.js中的任务
$ gulp
插件 : gulp-rev、gulp-rev-collector
Github : https://github.com/sindresorhus/gulp-rev
Github : https://github.com/shonny-ua/gulp-rev-collector
首先静态资源增长版本号发布这些牵扯到前端工程化问题,之于前端工程化,我这里不想过多解释,这里有篇讲解前端工程化的文章连接:https://www.zhihu.com/question/20790576
基本原理就是当静态资源发生版本更新后,用户浏览器会主动放弃缓存中的静态资源,从服务器拉取最新资源加载,而那些没有更新的静态资源文件则使用浏览器缓存,这样的好处就是既能提升用户访问网站的速度提高用户体验,还能减轻网站服务器压力。
要想达到这样的目的有两种思路:
非覆盖式发布:根据静态资源内容生成hash值,而后与文件名拼接生成新的静态资源文件,最后更新页面中静态资源引用路径。
这种方法须要注意的是,先上更新后的静态资源,再上页面文件。若是先上页面文件,页面中引用的静态资源路径是添加版本号的静态资源,因为服务器中不存在该版本号的静态资源,这个时候旧版页面加载不存在的静态资源就会致使页面布局错乱甚至报错。
这种方法的缺点也很是明显,每更新就会生成一次带版本号的静态资源文件,这样冗余的静态资源过多,因此须要本身定时清理掉老版本的静态资源。目前大公司通常都是使用这一种方法对静态资源进行版本迭代。
覆盖式发布:根据文件内容生成hash值,而后对引用该静态资源文件的模板连接增长版本参数。
这种方法不论是先上页面仍是静态资源,都会致使用户访问页面的时候出现问题,若是先上页面,新版页面加载旧版静态资源,致使页面布局错乱;若是先上静态资源,那些有旧版静态资源文件缓存的用户不会收到影响,可是新用户访问旧版页面加载的是新版静态资源,这样仍是会致使页面布局错乱等问题,因此若是必定要使用这种方法,那么最好是在页面访问量少的时间段先上静态资源文件,再上页面,固然这种方法比第一种方法的好处就是不会生成冗余的静态资源。
var gulp = require( 'gulp' ); var rev = require( 'gulp-rev' ); var revCollector = require( 'gulp-rev-collector' ); gulp.task( "default", function() { return gulp.src( "src/*.js" ) // 生成带hash版本号文件 .pipe( rev() ) // 保存新文件 .pipe( gulp.dest( "dist" ) ) // 生成新旧文件名对应的json文件 .pipe( rev.manifest() ) // 保存json文件 .pipe( gulp.dest( "dist" ) ); } );
参考资料:
http://www.ydcss.com/archives/424 http://www.gulpjs.com.cn/docs/getting-started/