时间:2021-05-25
之前,我介绍了学习安装并配置前端自动化工具Gulp,觉得gulp确实比grunt的配置简单很多,于是我决定再深入学习一下gulp,就去网上查了资料,发现gulp还可以自动添加版本号,这个功能就为我平时在更新css或js时老是在客户端存在缓存导致更新后的效果无法实时展现的苦恼。所以就赶紧去试了一下,果真可以,很高兴啊,真是为项目开发,为效果的快速展现提供了很多的便利。
实现原理:
1、修改js和css文件;
2、通过对js,css文件内容进行hash运算,生成一个文件的唯一hash字符串(如果文件修改则hash号会发生变化);
3、替换html中的js,css文件名,生成一个带版本号的文件名。
现在网上的方案都是生成一个新的dist目录,里面包含了要发布的html、js、css等文件。但是在实际的公司的项目中,会有情况不能生成新的HTML进行发布,需要在原来的HTML文件上进行js 、css版本的替换. 这里分享下我在实际项目中通过改动插件然后在原目录结构下进行版本的控制方案。(在这里,我有点不太明白原作者的意思,因为你既然修改了js或css,那么html中引入这些文件的版本号必然会发生变化,也就是html也跟着变化了,如果你不对新的html进行发布,那线上的html中的版本号还是老的版本号,就没有起到更新缓存的作用,那我们辛辛苦苦的配置gulp来添加这个版本号干嘛?)
原html文件代码
<link rel="stylesheet" href="../css/default.css"><script src="../js/app.js"></script>预期效果:在原目录结构下html文件代码
<link rel="stylesheet" href="../css/default.css?v=5a636d79c4"><script src="../js/app.js?v=3a0d844594"></script>background:url("../images/none.png?v=8f204d4")实现方法:
1、安装gulp和gulp插件
2、编写gulpfile.js
//引入gulp和gulp插件var gulp = require('gulp'), assetRev = require('gulp-asset-rev'), runSequence = require('run-sequence'), rev = require('gulp-rev'), revCollector = require('gulp-rev-collector');//定义css、js源文件路径var cssSrc = 'css/*.css', jsSrc = 'js/*.js';//为css中引入的图片/字体等添加hash编码gulp.task('assetRev', function(){ return gulp.src(cssSrc) //该任务针对的文件 .pipe(assetRev()) //该任务调用的模块 .pipe(gulp.dest('src/css')); //编译后的路径});//CSS生成文件hash编码并生成 rev-manifest.json文件名对照映射gulp.task('revCss', function(){ return gulp.src(cssSrc) .pipe(rev()) .pipe(rev.manifest()) .pipe(gulp.dest('rev/css'));});//js生成文件hash编码并生成 rev-manifest.json文件名对照映射gulp.task('revJs', function(){ return gulp.src(jsSrc) .pipe(rev()) .pipe(rev.manifest()) .pipe(gulp.dest('rev/js'));});//Html替换css、js文件版本gulp.task('revHtml', function () { return gulp.src(['rev*.json', 'View/*.html']) .pipe(revCollector()) .pipe(gulp.dest('View'));});//开发构建gulp.task('default', function (done) { condition = false; runSequence( //需要说明的是,用gulp.run也可以实现以上所有任务的执行,只是gulp.run是最大限度的并行执行这些任务,而在添加版本号时需要串行执行(顺序执行)这些任务,故使用了runSequence. ['assetRev'], ['revCss'], ['revJs'], ['revHtml'], done);});执行gulp命令后的效果
很显然这不是我们需要的效果
3、更改gulp-rev和gulp-rev-collector
打开node_modules\gulp-rev\index.js
第144行 manifest[originalFile] = revisionedFile;
更新为: manifest[originalFile] = originalFile + '?v=' + file.revHash;
打开nodemodules\gulp-rev\nodemodules\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-assets-rev\index.js
78行 var verStr = (options.verConnecter || "-") + md5;
更新为:var verStr = (options.verConnecter || "") + md5;
80行 src = src.replace(verStr, '').replace(/(\.[^\.]+)$/, verStr + "$1");
更新为:src=src+"?v="+verStr;
再执行gulp命令,得到的结果如下(效果正确):
但是假如我们更改了css和js后,再执行gulp命令,得到的结果会如下:
<link rel="stylesheet" href="../css/default.css?v=33379df310?v=803a7fe4ae"><script src="../js/app.js?v=3a0d844594?v=3a0d844594"></script>有没有发现,会在版本号后面再添加一个版本号,因为gulp只替换了原来文件名,这样又不符合预期效果了,所以我们想到,还需要修改插件的替换正则表达式。
4、继续更改gulp-rev-collector
打开node_modules\gulp-rev-collector\index.js
第107行 regexp: new RegExp( '([\/\\\\\'"])' + pattern, 'g' ),
更新为: regexp: new RegExp( '([\/\\\\\'"])' + pattern+'(\\?v=\\w{10})?', 'g' ),
现在你不管执行多少遍gulp命令,得到的html效果都是
以下是本人自己写的一个既可以编译less,又可以压缩、重命名css和js,同时可以压缩html并自动添加版本号的gulp.js配置文件,当然也是参考了原作者的方法:
//引入gulp和gulp插件var gulp = require('gulp'), less = require('gulp-less'), assetRev = require('gulp-asset-rev'), minifyCss = require('gulp-minify-css'), uglify = require('gulp-uglify'), htmlmin = require('gulp-htmlmin'), rename = require('gulp-rename'), imagemin = require('gulp-imagemin'), runSequence = require('run-sequence'), rev = require('gulp-rev'), revCollector = require('gulp-rev-collector');//定义css、js源文件路径var cssSrc = 'css/*.css', cssMinSrc = 'dist/css/*.css', jsSrc = 'js/*.js', jsMinSrc = 'dist/js/*.js', lessSrc = 'less/*.less', imgMinSrc = 'dist/images/*.{png,jpg,gif,ico}', htmlSrc = '*.html';//编译less 定义一个less任务(自定义任务名称)gulp.task('less', function(){ return gulp.src(lessSrc) //该任务针对的文件 .pipe(less()) //该任务调用的模块 .pipe(gulp.dest('css'));//编译后的路径});//为css中引入的图片/字体等添加hash编码gulp.task('assetRev', function(){ return gulp.src(cssSrc) //该任务针对的文件 .pipe(assetRev()) //该任务调用的模块 .pipe(gulp.dest('src')); //编译后的路径});//压缩cssgulp.task('cssMin', function() { return gulp.src(cssSrc) //压缩的文件 .pipe(rename({suffix: '.min'})) .pipe(minifyCss()) //执行压缩 .pipe(gulp.dest('dist/css')); //输出文件夹});//CSS生成文件hash编码并生成 rev-manifest.json文件名对照映射gulp.task('revCss', function(){ return gulp.src(cssMinSrc) .pipe(rev()) //文件名加MD5后缀 .pipe(rev.manifest()) //必须有这个方法 生成一个rev-manifest.json .pipe(gulp.dest('dist/css')); //将rev-manifest.json 保存到 dist/css 目录内});//压缩jsgulp.task('uglify',function(){ return gulp.src(jsSrc) .pipe(rename({suffix: '.min'})) .pipe(uglify()) .pipe(gulp.dest('dist/js'));});//js生成文件hash编码并生成 rev-manifest.json文件名对照映射gulp.task('revJs', function(){ return gulp.src(jsMinSrc) .pipe(rev()) .pipe(rev.manifest()) .pipe(gulp.dest('dist/js'));});//压缩htmlgulp.task('htmlMin',function(){ var options = { collapseWhitespace:true, //从字面意思应该可以看出来,清除空格,压缩html,这一条比较重要,作用比较大,引起的改变压缩量也特别大。 collapseBooleanAttributes:true, //省略布尔属性的值,比如:<input checked="checked"/>,那么设置这个属性后,就会变成 <input checked/>。 removeComments:true, //清除html中注释的部分,我们应该减少html页面中的注释。 removeEmptyAttributes:true, //清除所有的空属性。 removeScriptTypeAttributes:true, //清除所有script标签中的type="text/javascript"属性。 removeStyleLinkTypeAttributes:true, //清楚所有Link标签上的type属性。 minifyJS:true, //压缩html中的javascript代码。 minifyCSS:true //压缩html中的css代码。 }; return gulp.src(htmlSrc) .pipe(htmlmin(options)) .pipe(gulp.dest('dist/html'));});//Html替换css、js文件版本gulp.task('revHtml', function () { return gulp.src(['dist*.json', 'dist/html/*.html']) .pipe(revCollector()) .pipe(gulp.dest('dist/html'));});//压缩imagegulp.task('imageMin', function () { gulp.src('images/*.{png,jpg,gif,ico}') .pipe(imagemin()) .pipe(gulp.dest('dist/images'));});gulp.task('revImage', function(){ return gulp.src(imgMinSrc) .pipe(rev()) .pipe(rev.manifest()) //必须有这个方法 .pipe(gulp.dest('dist/images'));});gulp.task('default', function (done) { //condition = false; runSequence( //此处不能用gulp.run这个最大限度并行(异步)执行的方法,要用到runSequence这个串行方法(顺序执行)才可以在运行gulp后顺序执行这些任务并在html中加入版本号 'less', 'assetRev', 'cssMin', 'revCss', 'uglify', 'revJs', 'imageMin', 'revImage', 'htmlMin', 'revHtml', done);});目前,不知为何必须要运行两次gulp才可以给html中引入的图片添加版本号,所以还在摸索中,也请大神给指点指点,谢谢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
gulp是一个自动化构建工具,开发者可以用它来自动执行一些常见的任务。这里以我之前做的一个demo为例,简要介绍如何使用gulp实现前端工程自动化。项目结构其中
node.js中grunt和gulp的区别详解自nodeJS登上前端舞台,自动化构建变得越来越流行。目前最流行的当属grunt和gulp,这两个光看名字挺像,功
最近公司一个项目需要用到IAP升级,要求将APP的版本号在hex文件添加,于是尝试用python写一个脚本,运行之后可以自动增加版本号,并且日期都是当天的imp
很久以前,我们在"细说gulp"随笔中,以压缩JavaScript为例,详细地讲解了如何利用gulp来完成前端自动化。再来短暂回顾下,当时除了借助gulp之外,
springboot中集成jpa需要再pom文件中添加jpa的jar包,使用springboot的话iju不用自己规定版本号了,自动管理依赖版本即可。org.s