1.背景介绍
公司项目前端框架依赖于.net的aspx框架,代码迭代时间长,大部分代码较为老旧,资源文件(如js,css,图片等)与前端文件(html,aspx)依赖关系复杂,改动一个资源文件,为了去除缓存,需要修改多个地方的依赖版本。
对于一次完整的发布,所改动的资源文件数量较多,所需要改动的依赖版本号更是数量庞大,不免有所遗漏,导致缓存的存在.寻求一种一键自动统一替换依赖版本号的方案刻不容缓。
2.gulp的接入
2.1 gulp介绍
当下最热门的前端构建工具当属gulp和webpack,所谓“工欲善其事,必先利其器”,一个好的构建工具能大大提升开发效率,此处我们采用gulp实现资源版本的统一管理。
gulp是一个自动化构建工具,它能够将将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。
好的构建工具往往是由一系列插件组合而成,此处简单介绍一下gulp的一些常用插件:
gulp-imagemin 压缩图片
gulp-sass 将scss文件转为css
gulp-postcss 与autoprefixer配合使用
gulp-open 默认浏览器打开指定页面
gulp-htmlmin 最小化html文件
gulp-minify-css 最小化css
gulp-uglify 混淆js文件
gulp-concat 合并js,css文件
gulp-replace 对指定文件内容进行替换,可以用正则
gulp-usemin 将html中外链的css和js文件
gulp-zip 将文件打包成zip
gulp-sequence 串行执行任务,相对于gulp.task中依赖的任务是并行执行的
gulp-rev-all 对js或css文件加MD5戳,缓存用
gulp-asset-rev 资源文件替换
gulp-clean 清楚文件/文件夹
gulp-sequence 序列化执行task
gulp-bom 文件编码格式添加bom
2.2 gulpfile的文件编写
此处我们使用以上4个插件(gulp-asset-rev gulp-clean gulp-sequence gulp-bom)来实现统一修改版本的方案
首先我们先创建package.json引入插件与gulp:
//引入插件
"devDependencies": {
"gulp": "3.9.1",
"gulp-asset-rev": "0.0.15",
"gulp-clean": "0.3.2",
"gulp-bom": "3.0.0",
"gulp-sequence": "1.0.0",
},
然后我们需要创建gulpfile.js编写自动化流程
const gulp = require('gulp');
const clean = require('gulp-clean');
const assetRev = require('gulp-asset-rev');
const bom = require('gulp-bom');
const gulpSequence = require('gulp-sequence').use(gulp);
gulp.task('API', function() {
return gulp.src("./API/**/*").pipe(assetRev({verStr:'xx.xx.xx'})).pipe(bom('in')).pipe(gulp.dest('./dist/API'));
});
gulp.task('CMS', function() {
return gulp.src("./CMS/**/*").pipe(assetRev({verStr:'xx.xx.xx'})).pipe(bom('in')).pipe(gulp.dest('./dist/CMS'));
});
// 清理api
gulp.task('cleanAPI', function() {
return gulp.src('API', {read: false}) .pipe(clean())
});
// 清理cms
gulp.task('cleanCMS', function() {
return gulp.src('CMS', {read: false}).pipe(clean())
});
gulp.task('updateAPI', function() {
return gulp.src("./dist/API/**/*")
.pipe(bom('out')).pipe(gulp.dest('./API'));
});
gulp.task('updateCMS', function() {
return gulp.src("./dist/CMS/**/*")
.pipe(bom('out')).pipe(gulp.dest('./CMS'));
});
//删除已使用完毕的生成的文件夹,
gulp.task('clean', function() {
return gulp.src('dist', {
read: false
}).pipe(clean());
});
gulp.task('update-Api', gulpSequence('API', 'cleanAPI', 'updateAPI'))
gulp.task('update-CMS', gulpSequence('CMS', 'cleanCMS', 'updateCMS'))
//主要流程: 依次进行update-CMS,update-API,clean 3个task
gulp.task('default', gulpSequence('update-CMS','update-API','clean')); //gulp执行顺序
2.3 插件的修改
使用过程中发现插件的效果并不完全是我们想要的效果,所以需要对nodemodule中的插件进行代码修改,
gulp-asset-rev 改动地方如下:
( 1 ) 注释原有的版本替换,不符合我们的需求
//注释掉该段代码
//if (options.verStr) {
// src += options.verStr;
// return tag + '"' + src + '"';
//}
( 2 ) 因为原有文件已有版本号后缀,需要进行兼容,每次都重新添加
//新增该段代码
var assetIndex = assetPath.indexOf('?');
var srcIndex = src.indexOf('?');
if( assetIndex > -1 ){
assetPath = assetPath.substr(0,assetIndex);
}
if( srcIndex > -1 ){
src = src.substr(0,srcIndex);
}
( 3 ) glup-asset-rev使用的是本地文件的md5作为版本号,该方案的好处是只改动有新改动文件的依赖版本号,缺点是文件路径不规范或者使用网络地址的资源无法获取md5,添加使用统一传入的版本号作为备选方案
//修改
//如果获取md5
src = src += '?v=' + md5;
else{
//使用传入的版本号
if (options.verStr) {
src = src += '?v=' + options.verStr;
}
gulp-bom 改动地方如下:
( 1 ) aspx文件要求编码格式为utf-8 with bom格式,所以需要引入gulp-bom,但是图片等文件在utf-8 with bom的编码格式下将被损坏,所以需要过滤
//新增
var fileExtension = file.path.substring(file.path.lastIndexOf('.') + 1);
//产出输出 需要过滤.net框架文件
if (fileExtension != 'html' && fileExtension != 'aspx'
&& fileExtension != 'svc' && fileExtension != 'config'
&& fileExtension != 'cs' && fileExtension != 'pubxml') {
callback(null, file);
return;
}
2.4多人共同使用
以上本地修改了nodemodules中的三方package的代码,修改的内容在重新安装依赖就没有了,那要如何防止这种情况以及如何多人一起使用修改后的三方库代码呢.
一般常用办法有两个:
- 下载别人代码到本地,放在src目录,修改后手动引入。
- fork 别人的代码到自己仓库,修改后,从自己仓库安装这个插件。
此处我们使用patch-package来进行多人协作
首先引入
"dependencies": {
"patch-package": "6.2.2"
}
安装完后使用
npx patch-package gulp-asset-rev
npx patch-package gulp-bom
运行后会在项目根目录下的patches目录中创建2个补丁文件,补丁文件会在每次npm install的时候进行应用,达到多人共同使用的目的。
3.使用
3.1如何使用
相关自动化文件,补丁已经上传,等v4.5.3版本发布后,使用front_master新拉的分支都会有相关配置,使用起来较为简单:
第一步: npm install 安装依赖
第二步: gulp 执行gulpfile.js 进行自动化
如有报错,请查看node版本,npm版本
(ps:此处使用 node版本号 11.15.0 npm版本号 6.7.0)
3.2使用过程中的建议
在后续开发中,资源文件(js,css,图片)尽量使用相对路径,如
<script type="text/javascript" src="../static/js/base.js"></script>
而不是根目录表示法
<script type="text/javascript" src="/static/js/base.js"></script>