原理

修改js和css文件通过对js,css文件内容进行hash运算,生成一个文件的唯一hash字符串(如果文件修改则hash号会发生变化)替换html中的js,css文件名,生成一个带版本号的文件名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

方案

现在网上的方案都是生成一个新的dist目录,里面包含了要发布的html,js,css等文件。但是在实际的公司的项目中,会有情况不能生成新的HTML进行发布,需要在原来的HTML文件上进行js ,css版本的替换. 这里分享下我在实际项目中通过改动插件然后在原目录结构下进行版本的控制方案。

原html文件代码

<link rel="stylesheet" href="../css/default.css"><script src="../js/app.js"></script>
  • 1
  • 2

预期效果:在原目录结构下html文件代码

<link rel="stylesheet" href="../css/default.css?v=5a636d79c4"><script src="../js/app.js?v=3a0d844594"></script>
  • 1
  • 2

1:安装gulp和gulp插件 
执行:

npm install --save-dev gulpnpm install --save-dev gulp-revnpm install --save-dev gulp-rev-collectornpm install --save-dev run-sequence
  • 1
  • 2
  • 3
  • 4

2:编写gulpfile.js

//引入gulp和gulp插件var gulp = require('gulp'),    runSequence = require('run-sequence'),    rev = require('gulp-rev'),    revCollector = require('gulp-rev-collector');//定义css、js源文件路径var cssSrc = 'css/*.css',    jsSrc = 'js/*.js';//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('dev', function (done) {    condition = false;    runSequence(        ['revCss'],        ['revJs'],        ['revHtml'],        done);});gulp.task('default', ['dev']);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

执行gulp命令后的效果

//rev目录下生成了manifest.json对应文件{  "default.css": "default-803a7fe4ae.css"}<link rel="stylesheet" href="../css/default-803a7fe4ae.css"><script src="../js/app-3a0d844594.js"></script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

很显然这不是我们需要的效果

3.更改gulp-rev和gulp-rev-collector

打开node_modules\gulp-rev\index.js第136行 manifest[originalFile] = revisionedFile;更新为: manifest[originalFile] = originalFile + '?v=' + file.revHash;
  • 1
  • 2
  • 3
打开nodemodules\rev-path\index.js10行 return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`);更新为: return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);
  • 1
  • 2
  • 3
打开node_modules\gulp-rev-collector\index.js43
let cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );更新为: let cleanReplacement = path.basename(json[key]).split('?')[0];
  • 2
  • 3
打开node_modules\gulp-rev-collector\index.js第143行 regexp: new RegExp(  dirRule.dirRX + pattern , 'g' ),
更新为: regexp: new RegExp( dirRule.dirRX + pattern +'(\\?v=\\w{10})?', 'g' ),
如下:
// changes.push({ //regexp: new RegExp( dirRule.dirRX + pattern , 'g' ), regexp: new RegExp( dirRule.dirRX + pattern +'(\\?v=\\w{10})?', 'g' ), patternLength: (dirRule.dirRX + pattern).length, replacement: _.isFunction(dirRule.dirRpl) ? dirRule.dirRpl(manifest[key]) : closeDirBySep(dirRule.dirRpl) + manifest[key] });


  • 1
  • 2
  • 3

最终结果 
经过上面的四步修改之后现在你不管执行多少遍gulp命令,得到的html效果都是:

<link rel="stylesheet" href="../css/default.css?v=5a636d79c4"><script src="../js/app.js?v=3a0d844594"></script>