目标
前端的工作流程一些是这样: 写代码-》代码检查-》测试-》文件合并、压缩-》发布
前面的代码检查和测试我还没有做,不过目前我需要工具可以帮我做的事有下面两个:
- 能够帮我合并压缩代码
- 为了避免浏览器缓存问题,对于新发布的代码,需要能加上md5值,并且能自动修改我的html中对js/css的引用
安装
- 先从官网安装node.js,里面会带有npm工具。
- 再用npm来安装gulp
npm install --global gulp
- 进入项目目录,再安装一下项目的依赖
npm install --save-dev gulp
, –save-dev会自动加入到package.json中 - 每一个项目都需要一个gulpfile.js文件,我们后续的代码和配置就都在这个文件里面了,下面是一个例子:
var gulp = require('gulp');gulp.task('default', function() {// 将你的默认的任务代码放在这});
- 测试一下,看是否OK了,直接执行gulp吧。
以上的说明,来自官网Get Start
项目
我的项目是直播系统前端,主要功能是:
- 直播主页
- 列表页
- 个人信息页
- 直播页面,分Web/PC/Mobile/端,每个端页面不一样
- PC聊天页面
- 直播页面又分jwplayer7与jwplayer6的播放器
- 再加上语音WebRTC功能
项目Git地址在这里,纯前端代码在src/main/webapp/live目录中。
项目中已有package.json,checkout之后,直接执行npm install 会下载所有的依赖。然后再gulp会生成目标的html和js,这些文件可以用ftp直接放到tomcat的服务器中进行使用,请不要把这些文件用git上传。
至于CDN上传,可以走公司内部的CDN刷新功能上线就可以了。旧的文件可以不用管,所以不会有覆盖上线的问题。
代码
var gulp = require('gulp');
var concat = require('gulp-concat'); // 拼接工具
var uglify = require('gulp-uglify'); // 压缩工具
var rev = require('gulp-rev'); // 加md5后缀的工具
var revCollector = require('gulp-rev-collector'); //与rev共同使用
var useref = require('gulp-useref'); // 替换文件中的链接的工具,一般与gulp-rev共同使用
var minifyCss = require('gulp-minify-css'); // 压缩css工具
var del = require('del');
var gulpSequence = require('gulp-sequence');
// 任务处理的文件路径配置
var paths = {
indexJs: [
'compress/LivePlatform.js',
'compress/playerConfig.js',
'compress/chat.js',
'compress/netOptimize.js',
'compress/recordChat.js',
'compress/question.js',
'compress/liveEmotion.js',
'compress/pageinfo.js'
],
homeJs: [
'compress/LivePlatform.js',
'compress/home.js'
],
liveListJs: [
'compress/LivePlatform.js',
'compress/liveList.js'
],
myLiveJs: [
'compress/LivePlatform.js',
'compress/myList.js'
],
homeMobileJs: [
'compress/LivePlatform.js',
'compress/homeMobile.js'
],
webviewJs: [
'compress/LivePlatform.js',
'compress/liveEmotion.js',
'compress/app.js',
'compress/chat.js'
],
indexHtml:'html/index*.html',
liveMobileHtml:'html/liveMobile.html',
livePCHTML:'html/livePC.html',
homeHtml:'html/home.html',
liveListHtml:'html/liveList.html',
myLiveHtml:'html/myLive.html',
homeMobileHtml:'html/homeMobile.html',
webviewHtml:'html/webview.html'
};
/* 进行清理 */
gulp.task('clean', function () {
return del([
'dist/**/*',
'rev*',
'compress',
'*.html',
'*-*.js',
], function(){});
});
/* 进行压缩 */
gulp.task('compress', function () {
//先进行压缩
return gulp.src(['js/*.js', 'js/home/*.js'])
.pipe(uglify())
.pipe(gulp.dest('./compress'));
});
/* 进行压缩与合并,然后加md5文件后缀 */
gulp.task('concat', function() {
//处理index.html, index7.html, liveMobile.html的引用
gulp.src(paths.indexJs)
.pipe(concat('index.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revIndex/'));
//处理home.html
gulp.src(paths.homeJs)
.pipe(concat('home.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revHome/'));
//处理liveList.html
gulp.src(paths.liveListJs)
.pipe(concat('liveList.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revLiveList/'));
//处理myLive.html
gulp.src(paths.myLiveJs)
.pipe(concat('myLive.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revMyLive/'));
//处理homeMobile.html
gulp.src(paths.homeMobileJs)
.pipe(concat('homeMobile.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revHomeM/'));
//处理webview.html
return gulp.src(paths.webviewJs)
.pipe(concat('webview.js'))
.pipe(rev())
.pipe(gulp.dest('.'))
.pipe(rev.manifest())
.pipe(gulp.dest('./revWebview/'));
});
gulp.task('modifyRef', function() {
//处理index.html,index7.html,liveMobile,
//替换html中是js引用
gulp.src(['./revIndex/rev-manifest.json', paths.indexHtml])//用rev-manifest.json的模式来修改html文件
.pipe(revCollector())
.pipe(gulp.dest('.'));
gulp.src(['./revIndex/*.json', paths.liveMobileHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
gulp.src(['./revIndex/*.json', paths.livePCHTML])
.pipe(revCollector())
.pipe(gulp.dest('.'));
//处理home.html
gulp.src(['./revHome/*.json', paths.homeHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
//处理liveList.html
gulp.src(['./revLiveList/*.json', paths.liveListHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
//处理myLive.html
gulp.src(['./revMyLive/*.json', paths.myLiveHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
//处理homeMobile.html
gulp.src(['./revHomeM/*.json', paths.homeMobileHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
//处理webview.html
return gulp.src(['./revWebview/*.json', paths.webviewHtml])
.pipe(revCollector())
.pipe(gulp.dest('.'));
});
gulp.task('test', function() {
//处理index.html,index7.html,liveMobile,
//替换html中是js引用
gulp.src(['./revIndex/*.json','html/index.html'])//用rev-manifest.json的模式来修改html文件
.pipe(revCollector())
.pipe(gulp.dest('.'));
});
gulp.task('build', gulpSequence('clean', 'compress', 'concat'));
gulp.task('release', gulpSequence('modifyRef'));
gulp.task('default', ['release']);
注意点
- package.json中有所有的引用,直接在项目目录下面npm install 就可以安装好了。
- 一个大坑,可能是我不太会用的原因吧,任务的执行顺序是很重要的: 如果不在task中有return,会出问题; 用gulp接口中的task依赖会出问题,例如
gulp.task('release', ['compress'], function() {}
,另外就算用了gulp-sequenc这样的工具,如果涉及到写文件,也是有可能之前的文件还没有写好,但后面要用,依然会失败。这也是为什么我在release task里面把build和release分开的原因。按常理来说是没有问题的,但我反复实验,确实会失败.
另外听说gulp4.0中本身带顺序执行了,不知道是否还有这个坑。 - 我的代码写得还是复杂了一些,每一个html所依赖的js是分别压缩的,但这样修改起来比较方便。
- 至于grunt,反正现在主流也是用gulp来替代它了,所以用不用也就无所谓了。
- gulp.dest(‘dir’)只是把src中的以通配符或者最后的文件名写入到dir目录中而不是dir文件中。所以对于html来说,原文件名最好和要发布的就是同样的,否则还需要做rename操作,还得有依赖前一个写文件的操作已经结束。所以同名最简单。
- 上面的代码是确实可执行的,有编译问题可以找我。css我还没有处理,不过应该类似,可以自行处理。代码中有冗余,例如可以做成一个方法,另外后续有代码检查或者一键发布的功能了,后续再在这里补全。
资料
- 官网
- 官方文档
- gulp官方插件搜索列表
- 别的包,可以到这里找npmjs,里面的例子都很容易做实验的.