express+gulp构建项目(三)gulp任务

这次来看一看gulp是怎么工作的。
tasks/paths.js
paths.js文件里存放的是gulp任务中需要导入的文件的路径和导出的路径。
/**
* gulp.src 地址
* gulp.dest 地址
*/ var commonSrc = './public/**/*';
var widgetSrc = '!./public/widget/**/*.*';
var bowerSrc = '!./public/bower_components/**/*.*';
var fileOutput = '!./public/assets/**/*.*';
var nodeModulesSrc = '!./public/node_modules/**/*.*';
var nodeModulesEtcSrc = '!./public/etc/**/*.*';
var commonDest = './public/assets'; module.exports = {
js: {
src: [
commonSrc + '.js',
widgetSrc,
bowerSrc,
nodeModulesSrc,
nodeModulesEtcSrc,
fileOutput
],
dest: commonDest
},
node: {
src: ['./config/**/*.js', './controllers/**/*.js', './models/**/*.js', './swig/**/*.js']
},
img: {
src: [
commonSrc + '.png',
commonSrc + '.jpg',
commonSrc + '.jpeg',
commonSrc + '.gif',
commonSrc + '.bmp',
widgetSrc,
bowerSrc,
nodeModulesSrc,
nodeModulesEtcSrc,
fileOutput
],
dest: commonDest
},
css: {
src: [
commonSrc + '.css',
commonSrc + '.scss',
widgetSrc,
bowerSrc,
nodeModulesSrc,
nodeModulesEtcSrc,
fileOutput
],
dest: commonDest
},
cleanSrc: [
'./hash',
commonDest
]
};
这样子把gulp任务用到的路径集中到一个文件里面好管理,也方便。
gulp任务的路径书写方式是依照node-glob的语法。
glob语法基本如下:
*:匹配该路径段中0个或多个任意字符。
js/*.js
?:匹配该路径中1个任意字符。
js/?.js
[...]:匹配指定范围内的字符,与正则语法类似。
js/a[0-3].js
*(pattern|pattern|pattern):匹配括号中多个模型的0个或多个或任意个的组合,注意竖线|前后没有空格。
js/*(a|a1|b).js
!(pattern|pattern|pattern):匹配不包含任何模型。
js/!(a|b).js
?(pattern|pattern|pattern):匹配多个模型中的0个或任意1个,精确匹配,不可组合。
js/?(a|a2|b).js
+(pattern|pattern|pattern):匹配多个模型中的1个或多个。必须至少有一个,可以是这几个模型的组合。
js/+(a|a1|b).js
@(pattern|pattern|pattern):匹配多个模型中任意一个。精确匹配,不可组合,必须有一个,不可为空。
js/@(a|a1|b).js
**:可以匹配任何内容,但**不仅匹配路径中的某一段,而且可以匹配 'a/b/c' 这样带有'/'的内容,所以,它还可以匹配子文件夹下的文件。
**/@(a|a1|b).js
gulp_build.js
gulp_build文件是gulp任务主文件。
var gulp = require('gulp');//引入gulp自动化工具
var gulpif = require('gulp-if');//有条件的执行gulp任务
var runSequence = require('run-sequence');//运行多个gulp任务
var argv = require("yargs").argv;//接收用户在命令行输入的参数 例如:gulp build -s 中的 -s
var clean = require('gulp-clean');//删除文件或文件夹
var path = require('path'); //path模块用于处理和转换文件路径
var RevAll = require('gulp-rev-all-fixed');//静态资源版本迭代,解决文件缓存问题,其实就是给文件名后加上哈希值
var uglify = require('gulp-uglify');//js压缩
var cssmin = require('gulp-cssmin');//css压缩
var replace = require('gulp-replace');//字符串替换插件
var sass = require("gulp-sass");//预处理sass
var bower = require('gulp-bower');//下载bower包
var taskPaths = require('./tasks/paths'); //引入gulp任务所需要的路径
var jsonfile = require('jsonfile');//创建和解析json文件
var imgHashFile = {};
function getRevOpts(isDev) {//给gulp-rev-all-fixed模块生成选项的方法
var opt = {
hashLength: 12, //哈希值长度
transformFilename: function (file, hash) {
var ext = path.extname(file.path); //获取扩展名
var suffixes = isDev ? '' : '.' + hash.substr(0, 6); //获取哈希值前六位
if (ext.indexOf('scss') > 0) {//如果是scss文件,就变成css扩展名
ext = '.css';
}
return path.basename(file.path, ext) + suffixes + ext;
//path.basename(path, ext)返回路径的最后一段,例如./name/abc.html 则会返回abc.html
//path.extname(path, ext)返回路径最后一段的扩展名,例如./name/abc.html 则返回.html
//不带扩展名的基础文件名,后面连上哈希值,最后连上处理过的扩展名返回
}
};
return opt;
}
gulp.task('bower', function() {//bower任务,下载bower插件到以下目录
return bower({ directory: './public/bower_components' });
});
//clean任务,删除hash和assets文件夹下的文件,read: false参数使gulp不读取文件内容就进行删除,使操作变快
gulp.task('clean', function () {
return gulp.src(taskPaths.cleanSrc, { read: false })
.pipe(clean());
});
var temmoGulp = {
buildJs: function (src, dest, isDev, isWatching) {
var opts = {
fileNameManifest: 'js_hash.json',
hashLength: getRevOpts(isDev).hashLength,
transformFilename: getRevOpts(isDev).transformFilename
};
//gulp-rev-all-fixed选项,
//fileNameManifest,hash文件自定义命名
//transformFilename,自定义命名方法
var revAll = new RevAll(opts);//在将流导入revAll.revision()处理之前先要实例化RevAll对象
return gulp.src(src)
.pipe(uglify())
.pipe(revAll.revision())
.pipe(gulp.dest(dest))
.pipe(revAll.manifestFile()) //生成hash名单文件
.pipe(gulpif(!isWatching, gulp.dest('./hash'))); //将hash名单文件导入hash文件夹
},
buildImg: function (src, dest, isDev, isWatching) {
var opts = {
fileNameManifest: 'img_hash.json',
hashLength: getRevOpts(isDev).hashLength,
transformFilename: getRevOpts(isDev).transformFilename
};
var revAll = new RevAll(opts);
return gulp.src(src)
.pipe(revAll.revision())
.pipe(gulp.dest(dest))
.pipe(revAll.manifestFile())
.pipe(gulpif(!isWatching, gulp.dest('./hash')));
},
buildCss: function (src, dest, isDev, isWatching) {
var opts = {
fileNameManifest: 'css_hash.json',
hashLength: getRevOpts(isDev).hashLength,
transformFilename: getRevOpts(isDev).transformFilename
};
var revAll = new RevAll(opts);
var compassImporter = function(url, prev, done) {
if (!/^compass/.test(url)) {
return done({ file: url }); //如果url中不含compass
}
done({ file: 'compass-mixins/lib/' + url });
};
//url是当前导入的路径,prev是上一次处理的路径,done是可选回调函数
//outputStyle最终输出css的风格
//importer处理当遇到@import导入
//includePaths一个路径的数组让Libsass可以解决@import声明
//data传递给Libsass渲染
return gulp.src(src)
.pipe(sass({
outputStyle: 'compressed',
importer: compassImporter,
includePaths: [ 'node_modules' ],
data: '@import "compass"; .transition { @include transition(all); }'
}))
.pipe(sass().on('error', sass.logError))
.pipe(cssmin()) //压缩css
.pipe(replace(/(\.\.\/.*?(jpg|jpeg|gif|png|bmp){1})/mg, function ($1) {
//replace第二个参数如果是函数,每个匹配都调用该函数,它返回的字符串将作为替换文本使用
//$1参数是匹配到的字符串
var img = $1;
var imgRal = img.replace(/((\.\.\/){1,})(.*?(jpg|jpeg|gif|png|bmp){1})/g, '$1');
try {
imgHashFile = jsonfile.readFileSync('./hash/img_hash.json'); //读取img hash名单
} catch (e) {
imgHashFile = {};
}
for (var key in imgHashFile) {//循环img hash名单
if ((imgRal + key) === $1) {
img = '/static/assets/' + imgHashFile[key];
break;
}
}
return img; //将css中图片url文件名变为带hash的文件名
}))
.pipe(revAll.revision())
.pipe(gulp.dest(dest))
.pipe(revAll.manifestFile())
.pipe(gulpif(!isWatching, gulp.dest('./hash')));
}
};
var build = function () {
// 是否监听
var isDev = argv.dev === true;//若在命令行输入了dev参数,则isDev为真
gulp.task('js', function () {
return temmoGulp.buildJs(taskPaths.js.src, taskPaths.js.dest, isDev);
});
gulp.task('img', function () {
return temmoGulp.buildImg(taskPaths.img.src, taskPaths.img.dest, isDev);
});
gulp.task('css', function () {
return temmoGulp.buildCss(taskPaths.css.src, taskPaths.img.dest, isDev, false);
});
runSequence('clean', 'bower', 'js', 'img', 'css'); //顺序执行相关任务
};
gulp.task('build', function () { //build任务包含clean,下载bower包,处理js,处理img,处理css
return build();
});
var getFileName = function (str) {
var reg = /[^\\\/]*[\\\/]+/g; //获取路径里的文件名
str = str.replace(reg, '');
return str;
};
var getSinglePath = function (file) {
var filePath = file.path,
destPath,
fileName = getFileName(file.path);
filePath = filePath.replace(/(\\|\/)/img, '%');
//将路径里的/和\换成%
filePath = filePath.substring(filePath.indexOf('%public%'));
//从$public%开始截取
filePath = '.' + filePath.replace(/%/img, '/');
//将%替换回/,导入路径
destPath = filePath.replace(eval('/(' + fileName + ')$/mg'), '');
//去掉文件名
destPath = destPath.replace(eval('/\.\\/public\\//'), ('./public/assets/'));
//导出路径为./public/assets/下
return {
filePath: filePath,
destPath: destPath
};
};
gulp.task('watch', function () { //监控js,css,img的变动,如果变动,重新执行处理任务
gulp.watch(taskPaths.css.src, function (file) {
var paths = getSinglePath(file);
gulp.task('watchCss', function () {
return temmoGulp.buildCss(paths.filePath, paths.destPath, true, true);
});
runSequence('watchCss');
});
gulp.watch(taskPaths.js.src, function (file) {
var paths = getSinglePath(file);
gulp.task('watchJs', function () {
return temmoGulp.buildJs(paths.filePath, paths.destPath, true, true);
});
runSequence('watchJs');
});
gulp.watch(taskPaths.img.src, function(file) {
var paths = getSinglePath(file);
gulp.task('watchImg', function () {
return temmoGulp.buildImg(paths.filePath, paths.destPath, true, true);
});
runSequence('watchImg');
});
});
package.json里的scripts里的命令就是执行的gulp命令:
"scripts": {
"start": "node ./bin/www",
"dev": "./node_modules/.bin/gulp develop --gulpfile gulp_dev.js",
"ci": "./node_modules/.bin/gulp test --gulpfile gulp_test.js",
"assets": "./node_modules/.bin/gulp build --gulpfile gulp_build.js",
"assets_dev": "./node_modules/.bin/gulp build --dev --gulpfile gulp_build.js",
"watch": "./node_modules/.bin/gulp watch --gulpfile gulp_build.js"
}
npm run assets 是执行了gulp build,处理js,css,img等静态资源;npm run dev是执行了gulp develop,启动node服务;npm run watch执行gulp watch监听文件的变动。
gulp_dev.js
这个文件里是启动服务的gulp任务。
var gulp = require('gulp');
var nodemon = require('gulp-nodemon'); //监控文件变化,有变化则立即重启服务
gulp.task("develop", function () {
nodemon({
script: "bin/www",
ext: "js",
ignore: ['./public', './node_modules']
}).on("restart", function () {
console.log('restart');
});
});
gulp_test.js
执行eslint检测
var gulp = require('gulp');
var runSequence = require('run-sequence');
var eslint = require('gulp-eslint');
var taskPaths = require('./tasks/paths');
gulp.task('eslint_node', function () {
return gulp.src(taskPaths.node.src)
.pipe(eslint({
useEslintrc: './node.eslintrc'
}))
.pipe(eslint.format())
.pipe(eslint.failOnError());
});
gulp.task('test', function () {
runSequence('eslint_node')
});
express+gulp构建项目(三)gulp任务的更多相关文章
- express+gulp构建项目(二)启动项目和主文件
这一次整理的内容是项目主文件和如何启动项目. 启动项目 通过nodejs官网的例子https://nodejs.org/docs/latest-v4.x/doc/api/synopsis.html我们 ...
- 使用gulp构建项目
gulp.js作为一个前端构建工具,类似于webpack.Grountjs.rollupjs,不过相对于其他几种打包工具,gulp的使用更轻量,配置更简单,打包速度更快,今天不说他们几个的区别,也不说 ...
- express+gulp构建项目(一)项目目录结构
express是基于nodejs平台的web框架,它可以让我们快速开发出web引用.而gulp是一种自动构建工具,非常强大,有了它,能帮我们完成很多繁琐的工作,例如,静态文件的压缩,为静态文件加上哈希 ...
- express+gulp构建项目(五)swig模板
这里的文件负责配置swig模板引擎. index.js var jsonHash = require('./json_file'); var staticTag = require("./t ...
- express+gulp构建项目(四)env环境变量
这里的文件的作用是负责设置env环境变量和日志. index.js try { require('dotenv').load({silent: true}); //dotenv从一个.env文件中读取 ...
- express - 快速构建项目
1,cnpm i express -g 2, cnpm i express-generater -g 3, express - e 项目名
- 使用gulp搭建项目
项目源码地址 前期准备工作 首先确保本机安装了 node gulp中文文档 安装 gulp 命令行工具 npm install --global gulp-cli 在项目目录下创建 package.j ...
- 用gulp构建你的前端项目
前言 前端技术发展日新月异,随着模块化.组件化的提出,前端变得越来越复杂,静态资源越来越多,那么对静态资源的处理,如压缩,合并,去掉调试信息.. 如果还是人工去处理,效率非常之低且还容易出错,于是自动 ...
- gulp进阶构建项目由浅入深
gulp进阶构建项目由浅入深 阅读目录 gulp基本安装和使用 gulp API介绍 Gulp.src(globs[,options]) gulp.dest(path[,options]) gulp. ...
随机推荐
- 无光驱在32位windows系统下安装64位windows系统
位的系统. 大家都知道,32位的操作系统最多只能支持3.2G的内存,现在内存白菜价,很多人都在原有基础上购入新内存,这样最少也有4G了,为了让内存不浪费,我 们只有升级到64位操作系统.但是很多朋友又 ...
- windows下自动FTP的脚本
之前发过一篇如何自动FTP的文章,不过当时的脚本都是在Unix下测试通过的.而如果在windows下实现自动FTP的功能,则需要通过如下方式: 1. 建立ftp123.bat文件 open I ...
- 【iOS开发】在 App 中加入 AdMob 广告 - 入门介绍与编程技巧
前言 虽然在App中加入广告来盈利是比较低级的商业化方式,但对于个人开发者或者小团队开发者来说,做出一个简单易用的免费小工具(举个栗子),在里面加入一些广告,如果用的人多,也是可以带来一些可观的收入的 ...
- HttpClient 版本变化 转载
转载地址:http://my.oschina.net/u/577453/blog/173724 最近用到了HttpClient写爬虫,可能我有新版本强迫症,老是喜欢用新版本的东西(虽说新版本不一定好用 ...
- android ViewPager使用遇到的问题
项目需求是需要实现一个有两页可滑动的界面,就想到了使用ViewPager,在实现是没有深入考虑,就直接使用了PagerAdapter,页面是正常实现了,可是发现无法流畅的刷新页面(直接使用notify ...
- [MISC] JQUERY注意问题之ie8 post缓存
JQUERY 注意问题之 ie8 post缓存 1.设置AJAX,不存缓存 $.ajaxSetup ({ cache: false //关闭AJAX相应的缓存 }); 2.POST的URL加上随机参数 ...
- Android开发能够帮你更好开发的19个开发工具
要想快速开发一个Android应用,通常会用到很多工具,巧妙利用这些工具,能让我们的开发工作事半功倍,节省大量时间,下面大连Android开发培训小编就为大家介绍下这19个开发工具都有神马用途. 1. ...
- usr类库的使用(一般用在第三方类库使用系统库报错头文件找不到时)
第三方Html解析类库Hpple,在导入框架libxml2.2.dylib后,XCode仍然找不到<libxml/tree.h>. 1 .项目 -Targets 中的 Build P ha ...
- 网络HTTP协议
WebView:在应用中嵌入一个浏览器 ...... webView = (webView)findViewById(R.id.web_view); webView.getSettings().set ...
- EXCEL表格实现万位分隔符效果!
单击单元格右键 选择自定义单元格格式 选择数字标签 选择自定义 在输入框中输入:###","#### 单击确定即可! 格式刷可以对其他单元格实行同样效果!