最全gulp构建前端自动化开发环境
Gulp安装及常用组件配置安装
gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;gulp不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;类似的工具还有grunt,webpack,它们各有利弊。
简单表述一下gulp的使用安装:
安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务
下面我们开始构建前端开发一体化:
1、安装nodejs
gulp是基于nodejs,理所当然需要先安装nodejs
打开nodejs官网,下载对应版本即可,然后安装,安装路径随意,这里不多叙述。
2、安装git
git是分布式版本控制系统,现在的开源项目一般都放到公网上的git仓库上,如github, 项目中的使用的依赖包(开源项目)需要使用git从公网仓库中下载到本地。
windows 平台git 下载地址:
安装时下一步就可以 了。 默认安装地址 C:\Program Files (x86)\Git,安装完成后,在环境变量path中增加:C:\Program Files (x86)\Git\bin,目的是在cmd窗口中可以引用git命令。
进入cmd 窗 口:执行命令git --version,显示git版本号,则安装成功
3、Gulp安装
全局安装Gulpjs
npm install -g gulp
在项目下局部安装Gulpjs
查看是否正确安装:命令提示符执行 gulp -v,出现版本号即为正确安装。
4、npm介绍
npm(node package manager)nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等);
使用npm安装插件:命令提示符执行 npm install <name> [-g] [--save-dev];
全局安装 -g:将会安装在C:\Users\Administrator\AppData\Roaming\npm,并且写入系统环境变量;
非全局安装:将会安装在当前定位目录; 全局安装可以通过命令行在任何地方调用它,本地安装将安装在定位目录的node_modules文件夹下,通过require()调用;
--save:将保存配置信息至package.json(package.json是nodejs项目配置文件);
-dev:保存至package.json的devDependencies节点。
npm卸载插件:npm uninstall <name> [-g] [--save-dev]
npm更新插件:npm update <name> [-g] [--save-dev]
更新全部插件:npm update [--save-dev]
查看npm帮助:npm help
查看当前目录已安装插件:npm list
5、选装cnpm
因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,故我们采用 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
官方网址:http://npm.taobao.org;
命令提示符执行安装:
npm install cnpm -g --registry=https://registry.npm.taobao.org;
注意:安装完后最好查看其版本号 cnpm -v
注:cnpm跟npm用法完全一致,只是在执行命令时将 npm 改为 cnpm
6、新建package.json文件
命令提示符执行:
cnpm init
7、全局安装Gulpjs
命令提示符执行:
cnpm install gulp -g
8、局部安装Gulpjs
命令提示符执行:
cnpm install gulp --save-dev
安装提示选择回车即可。
9、安装bower
Bower是一个适合Web应用的包管理器,它擅长前端的包管理。
Bower安装
npm install -g bowe --save-dev
-g参数是全局安装,在哪个目录下执行这个命令都行,bower 最终被安装到 C:\Users\Administrator\AppData\Roaming\npm\node_modules\ (默认情况下)
打开 C:\Users\Administrator\AppData\Roaming\npm 目录,发现 node_modules 目录下已经安装了bower,并在npm目录中生成了可执行的命令 bower 和 bower.cmd。因此需要把 C:\Users\Administrator\AppData\Roaming\npm 加入 path 环境变量中。
执行命令显示bower版本:
bower --version
如图:
10、初始化bower
在项目目录下运行命令:
Bower init
按照提示一步一步创建即可
11、安装库
本案例安装以下几个常用的库,更多的库可以自行了解安装。
安装bootstrap(包含bootstrap和所依赖的jQuery)
bower install bootstrap --save-dev
安装微信官方网页开发样式库WeUi
bower install weui --save-dev
安装依赖库 angularjs
bower install angularjs --save-dev
如图所示:
库安装后,你会发现出现了相关文件,如何提取我们需要的核心文件,需要在gulpfile.js里面配置提取,具体步骤详见下面:
13、本地选择安装Gulp组件
这里我只举例一些常用的gulp组件,在gulp中,具有相同功能的组件往往有很多种,你可以选择自己熟练喜欢的使用,以下的组件将用在本文案例中。
从包依赖关系中加载gulp插件,并将它们作用到对象上
cnpm install gulp-load-plugins --save-dev
压缩html
cnpm install gulp-htmlmin --save-dev
压缩js
cnpm install gulp-uglify --save-dev
压缩css
cnpm install gulp-minify-css --save-dev
支持并编译less
cnpm install gulp-less --save-dev
支持并编译sass
cnpm install gulp-sass --save-dev
压缩图片
cnpm install gulp-imagemin --save-dev
生成雪碧图
cnpm install gulp.spritesmith --save-dev
清空文件夹
cnpm install gulp-clean --save-dev
合并文件
cnpm install gulp-concat --save-dev
重命名文件
cnpm install gulp-rename --save-dev
替换内容
cnpm install gulp-replace --save-dev
任务按需排序加载(支持异步和同步)
cnpm install gulp-replace --save-dev
把html里零碎的这些引入合并成一个文件,但是它不负责代码压缩
cnpm install gulp-useref --save-dev
更改版本号, gulp静态资源文件版本管理
cnpm install gulp-rev --save-dev
替换html中的引用路径
cnpm install gulp-rev-collector --save-dev
在gulp的管道流任务处理中,某个环节出了错,会导致整个任务中断(包括watch任务),gulp-plumber可以捕获处理任务中的错误,并且使任务不中断
cnpm install gulp-plumber --save-dev
显示报错信息并且在报错后不终止当前gulp任务,配合gulp-plumber使用
cnpm install gulp-notify --save-dev
生成sourcemap文件
cnpm install gulp-sourcemaps --save-dev
自动注入代码,无需刷新浏览器
cnpm install browser-sync --save-dev
只让修改过的文件通过管道
cnpm install gulp-changed --save-dev
js语法检查
cnpm install gulp-jshint --save-dev
配合 gulp-rev 使用,拿到生成的 manifest.json 后替换对应的文件名称。
cnpm install gulp-rev-replace --save-dev
服务器控制客户端同步刷新
cnpm install gulp-livereload --save-dev
以下组件可以根据个人喜好三选一,配合livereload组件完成服务器控制客户端同步刷新
暴露了一个HTTP服务器,并表达中间件,使用一个非常基本的REST API来实时监听通知服务器每一个特定的变化(自动刷新页面)。
cnpm install tiny-lr --save-dev
livereload需要在服务器上运行,如果你有自己的本地服务器也行,如果系统是win10或者8, 可能会出错,退出Node再以管理员的身份打开,重新安装即可
cnpm install http-server -g
利用gulp-webserve可以使用LiveReload来运行本地的Web服务器,达到同步刷新的效果
cnpm install gulp-webserve --save-dev
这里啰嗦一句,如果使用http-server 方式,则需要在html页面,写入:
<script>
document.write( '<script src="http://' + (location.host || 'localhost').split( ':' )[ 0 ] +
':35729/livereload.js?snipver=1"></' + 'script>' )
</script>
也可以引入相关js文件
在同步刷新时,是同时刷新浏览器所有窗口(例如:你同时开了多个项目,并且在浏览器中调试,则刷新时一起刷新),若其他项目也正在进行进行监听liverReload,则需要将其关闭,只能同时进行一个。
这里我根据自己项目的需求,选取了如下组件统一进行安装:
cnpm install gulp-load-plugins gulp-htmlmin gulp-uglify gulp-minify-css gulp-less gulp-sass gulp-imagemin gulp.spritesmith gulp-clean gulp-concat gulp-rename gulp-replace gulp-sync gulp-rev gulp-rev-collector gulp-plumber gulp-notify gulp-sourcemaps gulp-livereload --save-dev
再安装http-server:
cnpm install http-server -g
14、新建gulpfile.js文件(重要)
这里先放一个链接,gulp中文API
gulp只有4个核心API,十分简单:
gulp.task(name, fn) task定义一个gulp任务
gulp.watch(glob, fn) 监听当glob内容发生改变时,执行fn
gulp.src(globs[, options]) src方法是指定需要处理的源文件的路径,
gulp.dest(path[, options]) dest方法是指定处理完后文件输出的路径
以下是我的工作目录:
以下是我的配置表:
写的已经非常详细了,可以对照进行修改应用
/*
+----------------------------------------------------------------------------------------------------------------------------------------------
* Gulp - template file
* Create:2017.4
* Plugin Introduce :The plug-in is a navigation menu module, search module, combined with the switch animation effects, as well as back to the
top of the page animation effects as one of the multi-functional sidebar plug-in.
* Copyright (c) 2017.4 高仓雄(gcx / Spring of broccoli) In Hangzhou, China
* Contact :Wechat(lensgcx)
+----------------------------------------------------------------------------------------------------------------------------------------------
*/
var gulp = require( 'gulp' );
var gulpsync = require( 'gulp-sync' )( gulp ); //任务按需排序加载(支持异步和同步)
var plugins = require( "gulp-load-plugins" )( { pattern: '*' } ); //让gulp-load-plugins插件能匹配除了gulp插件之外的其他插件
//资源文件路径:
var path = {
all: '**/*.*', htmlAll: "**/*.html", cssAll: "**/*.css", cssMinAll: "**/*.min.css", jsAll: "**/*.js", jsMinAll: "**/*.min.js", lessAll: "**/*.less",
sassAll: "**/*.sass", scssAll: "**/*.scss", pngAll: "**/*.png", jsonAll: "**/*.json",
/* 总目录 */
Dist: "dist/", //发布根目录
Src: "src/", //开发根目录
Bower_components: "bower_components/", //bower库目录
revDst: "dist/rev/", //rev-json 生成总路径(包含css/js相关rev-json文件)
/* js */
jsSrc: "src/app/js/", //开发目录 JS脚本目标路径
jsDst: "dist/app/js/", //发布目录 JS脚本生成路径
jsLib: "dist/app/js/lib/", //发布目录 bower提取JS脚本
revJs: "dist/rev/js", //js rev-json 保存路径
/* less/sass/scss */
lssascSrc: "src/app/css/style/", //Less/Sass/Scss 转译目标路径
lssascDst: "src/app/css/translation/", //开发目录 转译生成路徑
/* html */
htmlSrc: 'src/view/', //html压缩 目标路径
htmlDst: 'dist/view/', //html压缩 目标生成路径
/* css */
cssSrc: "src/app/css/", //css压缩 目标路径
cssDst: 'dist/app/css/', //css压缩目标生成路径
cssLib: "dist/app/css/lib/", //发布目录 bower提取css脚本
revCss: "dist/rev/css/", //css rev-json 生成路径(全部任务结束后会删除)
/* img */
imgSrc: "src/app/img/", //ing压缩,所有目标对象
imgDst: "dist/app/img/", //img压缩目标路径
/* sprite */
imgSpriteSrc: "dist/app/img/plug/sprite", //sprite图生成材料(待合拼的图) 的目标路径
cssSprite: "src/app/css/sprite/", //sprite 生成css目录
imgSprite: "src/app/img/sprite/", //sprite 生成图片目录
imgSpriteDst: "app/img/sprite/", //sprite图(未压缩,sprite原图) 的生成路径
cssSpriteDst: "app/css/sprite/" //sprite-css样式文件 的生成路径
};
/*--------------------------------------------------------------------------------------------------------------------------------------------*/
//在每次操作gulp前先删除根目录下dist文件夹及其所有内容 和 sprite 生成的 css和png 文件,再进行压缩合并等操作
gulp.task( 'cleanDist', function()
{
return gulp.src( [ path.Dist, path.cssSprite, path.imgSprite, path.jsLib, path.cssLib ], { read: false } )//read:false,是不读取文件加快程序。
.pipe( plugins.clean() );
} );
/* del插件:删除当前文件所在的目录下的文件夹
不能删除其他盘或其他层级目录下的文件,即不能有../这样的情况 */
//gulp.task( 'clean', function( cb )
//{
// return plugins.del( [ 'dist/' ], cb );
//} );
/* 从bower库中提取核心到开发目录 */
gulp.task( 'bower-copy', function()
{
/* copy js */
gulp.src( path.Bower_components + 'jquery/dist/jquery.js' )
.pipe( gulp.dest( path.jsSrc + 'lib/jquery/' ) );
gulp.src( path.Bower_components + 'angular/angular.js' )
.pipe( gulp.dest( path.jsSrc + 'lib/angular/' ) );
gulp.src( path.Bower_components + 'bootstrap/dist/js/bootstrap.js' )
.pipe( gulp.dest( path.jsSrc + 'lib/bootstrap/' ) );
gulp.src( path.Bower_components + 'weui/dist/example/example.js' )
.pipe( gulp.dest( path.jsSrc + 'lib/weui/' ) );
/* copy css */
gulp.src( path.Bower_components + 'bootstrap/dist/css/bootstrap.css' )
.pipe( gulp.dest( path.cssSrc + 'lib/bootstrap/' ) );
gulp.src( path.Bower_components + 'weui/dist/style/weui.css' )
.pipe( gulp.dest( path.cssSrc + 'lib/weui/' ) );
} );
//JS压缩
gulp.task( 'js', function()
{
return gulp.src( [ path.jsSrc + path.jsAll, "!" + path.jsSrc + path.jsMinAll ] )
.pipe( plugins.uglify() )
.pipe( plugins.rename( {
//dirname: "gcx/gcx", //对象js文件父级文件名(路径),大批量不特定压缩js文件,则不建议使用
//basename: "gcx", //基本名,大批量不特定压缩js文件,则不建议使用
//prefix: "gcx-", //前缀名
suffix: ".min",
extname: ".js"
} ) )
.pipe( plugins.rev() ) //给js添加哈希值
.pipe( gulp.dest( path.jsDst ) )
.pipe( plugins.rev.manifest( { merge: true } ) ) //多个文件版本号写在一个rev-manifest.json文件里面
.pipe( gulp.dest( path.revDst + "js/" ) ); //json 保存路径
} );
/* css压缩 */
gulp.task( 'css', function()
{
return gulp.src( [ path.cssSrc + path.cssAll, "!" + path.cssSrc + path.cssMinAll ] ) //要压缩的文件
.pipe( plugins.minifyCss() ) //压缩
.pipe( plugins.rename( {
suffix: ".min",
extname: ".css"
} ) )
/*根据静态资源内容,生成md5签名,打包出来的文件名会加上md5签名,同时生成一个json用来保存文件名路径对应关系。
替换html里静态资源的路径为带有md5值的文件路径,这样html才能找到资源路径*/
.pipe( plugins.rev() )
.pipe( gulp.dest( path.cssDst ) ) //压缩后的文件路径
//添加版本号:并将经过优化和版本控制的文件输出到指定文件夹里。最后再用rev.manifest,将对应的版本号用json表示出来。
.pipe( plugins.rev.manifest( { merge: true } ) )
.pipe( gulp.dest( path.revDst + "css/" ) ); //json 保存路径
} );
/* Less转译 css */
/* 确保本地已安装gulp-sourcemaps,生成source map文件,Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应
的转换前的位置。有了它,出错的时候,出错工具将直接显示原始代码,而不是转换后的代码。这无疑给开发者带来了很大方便
确保本地已安装gulp-notify [cnpm install gulp-notify --save-dev] 用于任务提醒 / 处理报错
确保本地已安装gulp-plumber [cnpm install gulp-plumber --save-dev] 可以阻止 gulp 插件发生错误导致进程退出并输出错误日志。
例如:当编译less时出现语法错误或者其他异常,会终止watch事件,通常需要查看命令提示符窗口才能知道,这并不是我们所希望的,所以我们需要处理出现异
常并不终止watch事件(gulp-plumber),并提示我们出现了错误(gulp-notify)。*/
gulp.task( 'less', function()
{
gulp.src( path.lssascSrc + path.lessAll )
.pipe( plugins.plumber( { errorHandler: plugins.notify.onError( 'Error: <%= error.message %>' ) } ) )
.pipe( plugins.sourcemaps.init() )
.pipe( plugins.less() )
.pipe( plugins.minifyCss( { compatibility: 'ie7' } ) ) //兼容IE7及以下需设置compatibility属性 .pipe(cssmin({compatibility: 'ie7'}))
.pipe( plugins.sourcemaps.write() )
.pipe( gulp.dest( path.lssascDst ) );
} );
/* sass 转译 css */
gulp.task( 'sass', function()
{
return gulp.src( [ path.lssascSrc + path.sassAll, path.lssascSrc + path.scssAll ] )
.pipe( plugins.sass.sync().on( 'error', plugins.sass.logError ) )
.pipe( gulp.dest( path.lssascDst ) );
} );
/* 压缩图片任务 */
gulp.task( 'images', function()
{
return gulp.src( path.imgSrc + path.all )
.pipe( plugins.imagemin( { //压缩
progressive: true
} ) )
.pipe( gulp.dest( path.imgDst ) ); //另存图片
} );
/* 制作雪碧图 */
gulp.task( 'sprite', function()
{
return gulp.src( path.imgSpriteSrc + path.all ) //需要合并的图片地址
.pipe( plugins.spritesmith( { //制作雪碧图
imgName: path.imgSpriteDst + 'sprite.png', //保存合并后图片的地址
cssName: path.cssSpriteDst + 'sprite.css', //保存合并后对于css样式的地址
padding: 5, //合并时两个图片的间距
algorithm: 'binary-tree', //合并方式,有4种:
//cssTemplate:"handlebarsInheritance.sass.handlebars", //是生成css/sass 的模板文件(字符串)
cssTemplate: function( data )
{ //是生成css/sass 的模板文件(函数)
var arr = [];
data.sprites.forEach( function( sprite )
{
arr.push( ".sprite-" + sprite.name +
"{" +
"background-image: url('" + sprite.escaped_image + "');" +
"background-position: " + sprite.px.offset_x + " " + sprite.px.offset_y + ";" +
"width:" + sprite.px.width + ";" +
"height:" + sprite.px.height + ";" +
"}\n" );
} );
return arr.join( "" );
}
} ) )
.pipe( gulp.dest( path.Src ) );
} );
/* 制作完雪碧图后,再把 雪碧图 压缩生成到dist目录 */
gulp.task( 'spriteMin', function()
{
return gulp.src( path.Src + path.imgSpriteDst + path.all )
.pipe( plugins.imagemin( { progressive: true } ) )
.pipe( gulp.dest( path.Dist + path.imgSpriteDst ) )
} );
/* 合并文件 */
gulp.task( 'concat', [ 'sass', 'less', 'css', 'js' ], function()
{
//合并路径具有多样性,随机性,根据开发者需求变化而变化,故不单独写出,在concat中作为局部变量使用。
var cssAllSrc = [ 'src/app/css/style/plug/**/*.css', 'src/app/css/style/icon/**/*.css', 'src/app/css/sprite/**/*.css' ],
cssAllDst = 'src/app/css/merge/All';
var jsAllSrc = [ 'src/app/js/lib/jquery/jquery.js', 'src/app/js/jquery-easing.js', 'src/app/js/jquery-color.js' ],//合并顺序按照写入顺序进行
jsAllDst = 'src/app/js/merge/All';
/* 将src/app/css/style/icon/下所有压缩css文件,src/app/css/style/plug/下所有压缩css文件和src/app/css/sprite下所有压缩css文件
合并到 src/app/css/merge/All下,并且命名为all.min.css。*/
gulp.src( cssAllSrc )
.pipe( plugins.concat( 'all.css' ) )
.pipe( gulp.dest( cssAllDst ) );
// 将 src/app/js/ 下的 jquery-easing.min.js 和 jquery-color.min.js 文件 合并到 src/app/js/merge/All 下,并且命名为 easing.min.js
gulp.src( jsAllSrc )
.pipe( plugins.concat( 'easing.js' ) )
.pipe( gulp.dest( jsAllDst ) );
} );
/* 压缩html 任务 */
gulp.task( 'htmlmin', function()
{
var options = {
collapseWhitespace: true, //压缩HTML
collapseBooleanAttributes: false, //省略布尔属性的值 <input checked="true"/> ==> <input />
removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input />
removeScriptTypeAttributes: true, //删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css"
minifyJS: true, //压缩页面JS
minifyCSS: true //压缩页面CSS
};
return gulp.src( path.htmlSrc + path.htmlAll )
.pipe( plugins.htmlmin( options ) )
//.pipe(plugins.useref({ searchPath: '.tmp' }))
/* 更改html 引用路径:css/js文件的后缀名 */
.pipe( plugins.replace( '.css"', '.min.css"' ) )
.pipe( plugins.replace( '.js"', '.min.js"' ) )
.pipe( plugins.htmlmin( { collapseWhitespace: true } ) )
.pipe( gulp.dest( path.htmlDst ) )
} );
//改变引用路径 rev任务要在生成mainfest之后进行,可以用gulp[]任务依赖来进行流程控
gulp.task( 'rev', function()
{
gulp.src( [ path.revDst + path.jsonAll, path.htmlDst + path.htmlAll ] ) //读取 rev-manifest.json 文件 以及 需要进行名替换的目标文件(html)
.pipe( plugins.revCollector( { //替换html中的引用路径
replaceReved: true,
dirReplacements: {
//路径替换
//'css': '/dist/css/',
//'js/': '/dist/js/',
//'cdn/': function(manifest_value) {
// return '//cdn' + (Math.floor(Math.random() * 9) + 1) + '.' + 'exsample.dot' + '/img/' + manifest_value;
//}
}
} ) )
.pipe( gulp.dest( path.htmlDst ) );
/* 在MD5命名和路径替换之后,删除rev目录 */
gulp.src( path.revDst, { read: false } ) //src的第二个参数的{read:false},是不读取文件加快程序。
.pipe( plugins.clean() );
} );
/* 修改替换html文件中引入路径(若项目开发目录和生成目录的文件结构一样,则不需要替换修改路径 )*/
//gulp.task( 'replaceUrl', function()
//{
// gulp.src( path.htmlDst + path.htmlAll )
// .pipe( plugins.replace( '/src/', '/app/' ) ) //替换地址
// .pipe( plugins.htmlmin( { collapseWhitespace: true } ) )
// .pipe( gulp.dest( path.htmlDst ) )
//} );
/* 监控项目对象变化时显示的相关信息 */
var t = 0; //计数开始为0
var showinfo = function()
{
t++;
var curDate = new Date();
var Year = curDate.getFullYear().toString().slice( -2 );
var Month = ('0' + (curDate.getMonth() + 1)).slice( -2 );
var Day = ('0' + curDate.getDate()).slice( -2 );
var Hours = ("0" + curDate.getHours()).slice( -2 );
var Minutes = ("0" + curDate.getMinutes()).slice( -2 );
return FullDate = '\n' + ' - Author : 高仓雄(gcx / Spring of broccoli,Contact :Wechat(lensgcx)' + '\n' + ' - Date:' + Year + '-' + Month + '-' + Day + '-' + Hours + '-' + Minutes + '\n' + ' - Current: ' + t + 'st refresh loading... ' + '\n' + ' - running tasks...';
};
/* 使用 Chrome LiveReload Plug-in 和 tiny-lr 实现自动刷新页面 */
//gulp.task( 'watch', function() /* Rerun the task when a file changes */
//{
// //在浏览器中访问 http://localhost:35729/,正常情况下,你会在浏览器上看到类似于下面的 JSON 响应:{"tinylr":"Welcome","version":"1.0.4"}
// var port = 35729;
// plugins.tinyLr().listen( port, function( err ) //livereload
// {
// if( err )
// {
// return console.log( err )
// }
// gulp.watch( [ path.Src + path.all, path.htmlSrc + path.htmlAll ], function( event ) //监听启动时,控制台打印监听变化对象的出相关信息
// {
// console.log( 'File ' + event.path + ' was ' + event.type + showinfo() + '' );
// } );
// //gulp.watch(.......);
// } );
//} );
/* 使用webserver 自动刷新页面 */
//gulp.task( 'webserver', function()
//{
// gulp.src( './' ) // 服务器目录(./代表根目录)
// .pipe( plugins.webserver( { // 运行gulp-webserver
// livereload: true, // 启用LiveReload
// directoryListing: true, //是否显示目录列表
// open: true // 服务器启动时自动打开网页
// } ) );
//} );
/* gulp监听 Rerun the task when a file changes */
gulp.task( 'watch', function()
{
//reload 监听
plugins.livereload.listen();
gulp.watch( [ 'src/**/*.*', 'index.html' ], function( file )
{
plugins.livereload.changed( file.path ); //自动刷新页面
} );
gulp.watch( [ path.Src + path.all, path.htmlSrc + path.htmlAll, 'index.html' ], function( event )
{
console.log( 'File ' + event.path + ' was ' + event.type + showinfo() + '' ); //监听启动时,控制台打印监听变化对象的出相关信息
} );
//监听对象,在目标发生变化时,启动任务 work-xxxx
gulp.watch( [ path.lssascSrc + path.sassAll, path.lssascSrc + path.scssAll ], [ 'work-sass' ] );
gulp.watch( [ path.lssascSrc + path.lessAll ], [ 'work-less' ] );
gulp.watch( [ path.cssSrc + path.cssAll, "!" + path.cssSrc + path.cssMinAll ], [ 'work-css' ] );
gulp.watch( [ path.jsSrc + path.jsAll, "!" + path.jsSrc + path.jsMinAll ], [ 'work-js' ] );
gulp.watch( [ path.htmlSrc + path.htmlAll ], [ 'work-html' ] );
gulp.watch( [ 'src/app/fonts/**/*.*', 'src/app/info/**/*.*' ], [ 'work-copy' ] );
} );
/* 定义任务名及其触发任务
如:定义任务work-sass,既在任务 work-sass 触发时启动任务 sass */
gulp.task( 'work-sass', gulpsync.sync( [ 'sass' ] ) );
gulp.task( 'work-less', gulpsync.sync( [ 'less' ] ) );
gulp.task( 'work-css', gulpsync.sync( [ 'css' ] ) );
gulp.task( 'work-js', gulpsync.sync( [ 'js' ] ) );
gulp.task( 'work-html', gulpsync.sync( [ 'htmlmin', 'replaceSuffix', 'rev' ] ) );
gulp.task( 'work-copy', gulpsync.sync( [ 'copy' ] ) );
// 拷贝
gulp.task( 'copy', function()
{
gulp.src( 'src/app/fonts/**/*.*' )
.pipe( gulp.dest( 'dist/app/fonts/' ) );
gulp.src( 'src/app/info/**/*.*' )
.pipe( gulp.dest( 'dist/app/info/' ) );
} );
/* 打包生成发布项目文件 */
//定义图片操作任务(images, sprite, spriteMin),将图片压缩后,生成雪碧图,再压缩雪碧图到生成目录
gulp.task( 'img-handle', gulpsync.sync( [ 'images', 'sprite', 'spriteMin' ] ) );
//定义常规任务(在图片操作任务之后,进行常规任务(sass, less, css, js),并进行合并)
gulp.task( 'normal', gulpsync.sync( [ 'img-handle', 'bower-copy', 'concat', [ 'sass', 'less', 'css', 'js' ] ] ) );
//定义替换链接任务collector ( 再完成常规任务的前提下:先在所有html文件中替换css/js的后缀名,再进行rev操作替换html模板中的链接)
gulp.task( 'collector', gulpsync.sync( [ 'normal', 'htmlmin', 'rev' ] ) );
//使用 gulp.task('default') 定义自动化任务默认执行入口,在命令行使用 gulp 启动所有任务,先清除目标生成文件,完成一系列操作后,再启动监听。
gulp.task( 'default', gulpsync.sync( [ 'cleanDist', 'collector', 'copy', 'watch' ] ) );
/* 使用gulp-sequence来顺序异步加载任务列表 */
//var gulpSequence = require( 'gulp-sequence' );
//gulp.task( 'default', [ 'clean' ], function( cb )
//{
// gulpSequence( 'cleanDist', [ 'images', 'sprite', 'spriteMin' ], [ 'sass', 'less', 'css', 'js' ], 'concat', 'htmlmin', 'replaceSuffix', 'rev', 'replaceUrl', 'cleanRev', 'watch' )( cb );
//} );
注意一下:
通过对js,css文件内容进行hash运算,生成一个文件的唯一hash字符串,替换html中的js,css文件名,生成一个带版本号的文件名。
正常操作下,我们将得到如下::
<link rel="stylesheet" href="../../app/css/other/other1-5a636d79c4.css">
实际上,我们预期是想得到:
<link rel="stylesheet" href="../../app/css/other/other1.css?v=5a636d79c4">
故而,我们需要更改更改 gulp-rev和gulp-rev-collector
打开node_modules\gulp-rev\index.js
第144行 manifest[originalFile] = revisionedFile;
更新为: manifest[originalFile] = originalFile + '?v=' + file.revHash;
打开nodemodules\gulp-rev\node_modules\rev-path\index.js
10行 return filename + '-' + hash + ext;
更新为: return filename + ext;
打开node_modules\gulp-rev-collector\index.js
31行if ( !_.isString(json[key]) || path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' ) !== path.basename(key) ) {
更新为: if ( !_.isString(json[key]) || path.basename(json[key]).split('?')[0] !== path.basename(key) ) {
打开node_modules\gulp-rev-collector\index.js
第107行 regexp: new RegExp( '([\/\\\\\'"])' + pattern, 'g' ),
更新为: regexp: new RegExp( '([\/\\\\\'"])' + pattern+'(\\?v=\\w{10})?', 'g' ),
全部更改完毕后,执行下步gulp命令,则我们得到的结果将符合我们的预期:
15、运行gulp
命令提示符执行:
当执行 gulp default 或 gulp 将会调用default任务里的所有任务
如下图所示,则成功搭建:
16、结语
至此,所有步骤已经完成,gulp相关插件有非常多,你可以多去社区尝试下载使用。
因水平时间有限,本文若有错误之处,欢迎指正。
参考资料:
http://www.dbpoo.com/getting-started-with-gulp/
http://www.cnblogs.com/YikaJ/p/4267577.html
http://www.unjeep.com/q/452992984.htm
http://www.bluesdream.com/blog/gulp-frontend-automation-introduction-and-livereload.html
http://www.cnblogs.com/johnnydan/p/4667905.html
http://blog.csdn.net/zchcode/article/details/52421871