原理
修改 js 和 CSS 文件
通过对 js,css 文件内容进行 hash 运算, 生成一个文件的唯一 hash 字符串 (如果文件修改则 hash 号会发生变化)
替换 html 中的 js,css 文件名, 生成一个带版本号的文件名
方案
现在网上的方案都是生成一个新的 dist 目录, 里面包含了要发布的 html,js,css 等文件. 但是在实际的公司的项目中, 会有情况不能生成新的 HTML 进行发布, 需要在原来的 HTML 文件上进行 js ,css 版本的替换. 这里分享下我在实际项目中通过改动插件然后在原目录结构下进行版本的控制方案.
原 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>
1: 安装 gulp 和 gulp 插件
执行:
- npm install --save-dev gulp
- npm install --save-dev gulp-rev
- npm install --save-dev gulp-rev-collector
- npm install --save-dev run-sequence
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']);
执行 gulp 命令后的效果
- //rev 目录下生成了 manifest.json 对应文件
- {
- "default.css": "default-803a7fe4ae.css"
- }
- <link rel="stylesheet" href="../css/default-803a7fe4ae.css">
- <script src="../js/app-3a0d844594.js"></script>
很显然这不是我们需要的效果
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;
打开 nodemodules\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) ) {
再执行 gulp 命令, 得到的结果如下 (效果正确):
- <link rel="stylesheet" href="../css/default.css?v=803a7fe4ae">
- <script src="../js/app.js?v=3a0d844594"></script>
但是假如我们更改了 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 效果都是
- <link rel="stylesheet" href="../css/default.css?v=5a636d79c4">
- <script src="../js/app.js?v=3a0d844594"></script>
转载自 https://segmentfault.com/a/1190000006204457
来源: http://www.qdfuns.com/article/45988/4a75c49b3045b141a7c80022b9b4f594.html