gulp作为前端自动化工具本质上是文件的自动化批处理,所以理论山无论是javaEE,php,rail应该都是可以应用的。
这里给大家介绍一下我在实际javaEE项目里的自动化实践。
1、想达到什么目的?
这个一定要在一开始就有一些具体的想法。
这里想对js、css等资源文件进行压缩,并且通过md5实现版本管理,解决服务器端更新后用户浏览器缓存的问题。
并且将所有资源文件上传cdn,并自动替换jsp中的原路径,增加页面加载速度。
2、实现过程
常规的压缩、md5、上传cdn是比较简单的,但是jsp的路径替换就比较麻烦,路径里经常有${XXX }类似的东西,如果之前没有对自动化的规划的话,很多的资源路径可能都是拼出来的,这对替换路径造成了一定的困扰。
同时,gulp生成的新资源文件要保持原有路径,在原资源文件(如js)进行新的开发后要能够用自动化工具一件发布到正式环境(这意味着对新文件的压缩-md5-上传cdn-替换路径),并且能做到生产环境和开发环境的简易切换。(总不能每写两行代码就运行一下自动化脚本,然后刷新页面再看效果吧)。
所以这里先架构了如何在较少的改变原项目结构的情况切换生产和测试的前端环境:
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/pages/" p:suffix=".jsp" p:contentType="text/html; charset=utf-8" />
这里是开发环境中spring的配置文件,在所有java文件中引入的jsp文件的路径自动加上/WEB-INF/pages/前缀,但在生产环境我们可以改成这样:
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/propages/" p:suffix=".jsp" p:contentType="text/html; charset=utf-8" />
前缀变成了propages,所以我们经过压缩,路径替换生成的jsp文件要在保持原有路径结构的情况下生成在和pages目录同级别的propages目录下。
3、gulpfile.js
const gulp = require('gulp');
const replace = require('gulp-replace');
const changed = require('gulp-changed');
const uglify = require('gulp-uglify');
const filter = require('gulp-filter');
const minifyCss = require('gulp-minify-css'); //- 压缩CSS为一行;
const qn = require('gulp-qn');
const rev = require('gulp-rev'); //- 对文件名加MD5后缀
const revCollector = require('gulp-rev-collector');
const runSequence = require('run-sequence');//控制task顺序
const qiniu_options = {
accessKey: 'XXXXXX',
secretKey: 'XXXXXX',
bucket: 'resources',
domain: 'XXXXXX.bkt.clouddn.com'
};
gulp.task('build-js', function () {
return gulp.src(['src/main/webapp/**/*.js'])
//压缩js
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest('dist'))
.pipe(rev.manifest())
.pipe(gulp.dest('dist/rev/js'));
});
gulp.task('build-css', function () {
return gulp.src(['src/main/webapp/**/*.css'])
//压缩css
.pipe(minifyCss())
.pipe(rev())
.pipe(gulp.dest('dist'))
.pipe(rev.manifest())
.pipe(gulp.dest('dist/rev/css'));
});
gulp.task('build-images', function () {
return gulp.src(['src/main/webapp/**/*.png','src/main/webapp/**/*.jpg','src/main/webapp/**/*.gif'])
.pipe(rev())
.pipe(gulp.dest('dist'))
.pipe(rev.manifest())
.pipe(gulp.dest('dist/rev/images'));
});
gulp.task('upload-cdn-js', function () {
return gulp.src(['dist/**/*.js'])
.pipe(qn({
qiniu: qiniu_options,
prefix: 'front'
}))
});
gulp.task('upload-cdn-css', function () {
return gulp.src(['dist/**/*.css'])
.pipe(qn({
qiniu: qiniu_options,
prefix: 'front'
}))
});
gulp.task('upload-cdn-images', function () {
return gulp.src(['dist/**/*.png','dist/**/*.jpg','dist/**/*.gif'])
.pipe(qn({
qiniu: qiniu_options,
prefix: 'front'
}))
});
gulp.task('upload-cdn-srcimages', function () {
return gulp.src(['src/main/webapp/**/*.png','src/main/webapp/**/*.jpg','src/main/webapp/**/*.gif'])
.pipe(qn({
qiniu: qiniu_options,
prefix: 'images'
}))
});
gulp.task('build-upload', function (callback) {
runSequence(['build-js', 'build-css', 'build-images'],
['upload-cdn-js', 'upload-cdn-css', 'upload-cdn-images'],
callback);
});
gulp.task('build-jsp', function () {
return gulp.src(['dist/rev/*.json', 'src/main/webapp/WEB-INF/pages/**/*.jsp'], {base: 'src/main/webapp/WEB-INF/pages'})
.pipe(revCollector({
replaceReved: true,
dirReplacements: {}
}))
.pipe(minifyHTML({
empty: true,
spare: true
}))
.pipe(gulp.dest('src/main/webapp/WEB-INF/propages'));
});
gulp.task('replace-jsp', function () {
return gulp.src(['src/main/webapp/WEB-INF/propages/**/*.jsp'])
.pipe(replace(/XXXX/g, qiniuDomain)) //这里比较吃正则,每个项目的替换正则都是不一样的
.pipe(gulp.dest('src/main/webapp/WEB-INF/propages'));
});
gulp.task('default', function (callback) {
runSequence(
'build-upload',
'build-jsp',
'replace-jsp',
callback);
});
//gulp.task('watch', function () {
// gulp.watch('**', ['default']);
//});