gulp动态生成html内的css、js版本号
一、功能(解放生产力,提高团队开发效率):
1、通过gulp命令行方式动态切换环境变量的值;
2、自动给html引入的css,js文件批量添加版本号;
二、操作流程:
该流程基于npm命令安装包,假设你的电脑环境已经安装了node环境。
1、切换到项目所在根目录,执行npm init 生成package.json文件;
2、执行 npm install -g gulp@3.9.1 全局安装gulp;
3、依次执行
npm install --save-dev gulp-rev
npm install --save-dev gulp-rev-collector
npm install --save-dev run-sequence
npm install --save-dev minimist
4、在根目录下创建gulpfile.js文件,该文件主要用于指定要执行什么任务以达到我们想要的效果;(具体逻辑参考下面的gulpfile.js)
5、执行gulp --env test --dir demo(--env【必填】 后面的参数表示要切换到哪个环境,--dir demo【非必填】后面的参数表示要以哪个目录下的同名文件为准);
<link rel=
"stylesheet"
href=
"../css/default-803a7fe4ae.css"
>
<script src=
"../js/app-3a0d844594.js"
></script>
很显然这不是我们需要的效果;
修改插件配置,因插件版本更新,更改的行数可能会略有差异
1、路径 node_modules/gulp-rev/index.js
第135行 manifest[originalFile] = revisionedFile;
更改为 manifest[originalFile] = originalFile + '?v=' + file.revHash;
2、路径 node_modules/gulp-rev-collector/index.js
第40行 var cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );
更改为 var cleanReplacement=path.basename(json[key]).split('?')[0];
第173行 regexp: new RegExp( prefixDelim + pattern, 'g' ),
更改为 regexp: new RegExp( prefixDelim + pattern+'(\\?v=\\w{10})?', 'g' ),
3、路径 node_modules/rev-path/index.js
第9行 return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`);
更改为 return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);
6、操作实例:
纵向文件夹顺序:a ->b
a/css/index.css
b/css/index.css
--------------------
操作1:修改a/css/index.css文件后,执行 gulp --test 。
结果:a/css/index.html的引入a/css/index.css文件版本号不变。
------------------------------
操作2:修改a/css/index.css文件后,执行 gulp --test --dir a 。
结果:a、b文件下引用的index.css版本号都同步改变。
7、参考文档:https://www.jianshu.com/p/2e554161b930
gulpfile.js
//引入gulp和gulp插件, var gulp = require('gulp'), runSequence = require('run-sequence'), rev = require('gulp-rev'), revCollector = require('gulp-rev-collector'); minimist = require('minimist') const fs = require('fs'); const path = require('path'); var env = ""; //环境变量 var dir = ""; //这个参数表示当不同目录下存在同名的js或者css(比如carnival/css/index.css,womensDay/css/index.css)文件时,最终以哪个目录下的为准; var allDirs = getAllDirs(); // 获取当前所有的目录 var envs = ["dev", "test", "pre", "release"]; //对应的各个环境变量的值 (从env.js文件获取) // 接受命令行参数 var knownOptions = { string: 'env,dir', // 接收的命令行参数 default: { env: "release", dir: allDirs } }; var options = minimist(process.argv.slice(2), knownOptions); env = options.env; // 由于活动目录下的js或者css文件夹下的某些js,css文件会有同名冲突,所以加了一个dir参数来表示以哪个为准; // (例如,carnival/css/index.css,跟womensDay/css/index.css,在构建的时候最终以womensDay[按遍历顺序,最后push进数组]的为准,这时候你修改carnival/css/index.css这个文件, // 之后进行构建,是不生效的,这个时候我们可以指定以carnival为准,那么修改carnival/css/index.css这个文件后重新构建是可以生效的) dir = options.dir; if (process.argv.indexOf("--env") < 0 || process.argv.indexOf("--env") > 0 && process.argv.length < 4) { return console.error("请输入环境变量,例如:gulp --env test"); } if (process.argv.indexOf("--dir") > 0 && process.argv.length < 6) { return console.error("请正确的目录参数名,例如:gulp --dir demo"); } if (envs.indexOf(env) < 0) { return console.error("环境变量值不存在,请输入正确的环境变量的值!"); } if (dir) { if (typeof dir == "string") { if (allDirs.indexOf(dir) >= 0) { allDirs.splice(allDirs.indexOf(dir), 1) allDirs.push(dir) } else { return console.error("目录名不存在,请输入正确的目录名"); } } } var fileData = ""; // 读取env.js文件,动态修改env变量(这个修改方式只适用于环境变量那行只有类似这段文本var env ="test",否则的话就按照你的算法自己处理它,修改下面的方法就可以了) fs.readFile('js/env.js', function (err, data) { if (err) { return console.error(err); } var dataStr = data.toString(); dataStr.trim().split('\n').forEach(function (v, i) { if (/varenv=/.test(v.replace(/\s*/g,""))) {// 这里切换环境变量的值,先去除所有空格,再进行正则表达式的比较 fileData += 'var env = "' + env + '";' + "\n" } else { fileData += v + "\n"; } }) // 将文本内容重新写入env.js fs.writeFile('js/env.js', fileData, (err) => { if (err) throw err; }); }) function getAllDirs(mypath = '.') { var excluedeDirs = [".vscode", "js", "css", "node_modules", "rev"] //排除的文件夹(只保留每个活动目录对应的名字,这些文件夹下对应的html文件里的js,css才需要动态修改版本号) const items = fs.readdirSync(mypath); let result = []; // 遍历当前目录中所有的文件和文件夹 items.map(item => { let temp = path.join(mypath, item); // 若当前的为文件夹 if (fs.statSync(temp).isDirectory()) { if (excluedeDirs.indexOf(item) < 0) { result.push(item); // 存储当前文件夹的名字 } } }); return result; } var revHtmls = []; //定义css、js源文件路径 var cssSrc = ['css/*.css']; var jsSrc = ['js/*.js']; allDirs.forEach(function (item, index) { //Html替换css、js文件版本 gulp.task('revHtml' + (index + 1), function () { return gulp.src(['rev/**/*.json', item + '/*.html']) // 这里的View/*.html是项目html文件路径,如果gulpfile.js和html文件同在一级目录下,修改为return gulp.src(['rev/**/*.json', '*.html']); .pipe(revCollector()) .pipe(gulp.dest(item));// 注意这里是生成的新的html文件,如果设置为你的项目html文件所在文件夹,会覆盖旧的html文件,若上面的View/*.html修改了,这里也要相应修改,如果gulpfile.js和html文件同在一级目录下,修改为 .pipe(gulp.dest('')); }); revHtmls.push('revHtml' + (index + 1)) cssSrc.push(item + '/css/*.css') jsSrc.push(item + '/js/*.js') }) // //清空目标文件 // gulp.task('cleanDst', function () { // return gulp.src(['rev'], { read: false }) // .pipe(clean()); // }); // //检查js语法 // gulp.task('jslint', function () { // return gulp.src(jsSrc) // .pipe(jshint()) // .pipe(jshint.reporter('default')); // }); //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')); }); //开发构建 gulp.task('default', function (done) { condition = false; runSequence(['revCss'], //需要说明的是,用gulp.run也可以实现以上所有任务的执行,只是gulp.run是最大限度的并行执行这些任务,而在添加版本号时需要串行执行(顺序执行)这些任务,故使用了runSequence. ['revJs'], revHtmls, done) });