zoukankan      html  css  js  c++  java
  • 使用gulp自动化打包合并前端静态资源(CSS、JS文件压缩、添加版本号)

    现在正在做的项目更新迭代比较频繁,会经常对前端代码打包部署,手动整合代码文件很麻烦并且浪费时间,所以决定使用gulp来代替手工完成这项工作。

    前端静态资源在发版更新时会面临客户端浏览器缓存的问题(可参考这篇文章),解决这个问题可以采用两类方法:覆盖方法(引用资源时加版本号,不修改资源文件名)、非覆盖方法(修改资源文件名),本篇文章主要采用的是第一种加版本号的方式,主要用gulp给静态资源自动加版本号和压缩CSS、JS。

    原理:通过对JS,CSS文件内容进行Hash运算,生成一个文件的唯一Hash字符串,若对文件内容进行了修改则Hash号会发生变化。在HTML中引用文件时将版本号加在后面。

    原始HTML:

    1 <link href="css/global.css" rel="stylesheet" type="text/css" />
    2 <script src="js/fun.js"></script>

    使用后HTML:

    1 <link href="css/global.css?v=b40a6f2a9f" rel="stylesheet" type="text/css" />
    2 <script src="js/fun.js?v=3a08b5fa87"></script>

    一、环境配置(安装gulp)

    首先安装node、npm(此处省略)

    安装gulp以及用到的插件,并在项目目录下创建文件gulpfile.js。

    $ npm install --global 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
    $ npm install --save-dev gulp-clean
    $ npm install --save-dev gulp-minify-css
    $ npm install --save-dev gulp-uglify

    在项目目录下创建文件gulpfile.js

    项目目录结构:

    node_modules中是安装的gulp和各种插件

    二、编写gulpfile.js

     1 //引入gulp和gulp插件
     2 var gulp = require('gulp'),
     3     runSequence = require('run-sequence'),
     4     rev = require('gulp-rev'),
     5     clean = require('gulp-clean'),
     6     minifycss=require('gulp-minify-css'),
     7     uglify=require('gulp-uglify'),
     8     revCollector = require('gulp-rev-collector');
     9 
    10 //定义css、js源文件路径
    11 var cssSrc = './**/*.css',            //选择目录下所有css
    12       jsSrc = './**/*.js',     //选择目录下所有css
    13       srcExclude = '!./node_modules/**/*',    //排除node_modules中的文件
    14       cssFile = 'css/**/*',    //css文件夹
    15       imageFile = 'image/**/*',    //图片文件夹
    16       jsFile = 'js/**/*',    //js文件夹
    17       jsCompressPath = 'Publish/js/*.js',    //压缩Publish中的js
    18       cssCompressPath = 'Publish/css/*.css';    //压缩Publish中的css
    19 
    20 
    21 //CSS生成文件hash编码并生成 rev-manifest.json文件名对照映射
    22 gulp.task('revCss', function(){
    23     return gulp.src([cssSrc, srcExclude])
    24         .pipe(rev())
    25         .pipe(rev.manifest())
    26         .pipe(gulp.dest('rev/css'));
    27 });
    28 
    29 //js生成文件hash编码并生成 rev-manifest.json文件名对照映射
    30 gulp.task('revJs', function(){
    31     return gulp.src([jsSrc, srcExclude])
    32         .pipe(rev())
    33         .pipe(rev.manifest())
    34         .pipe(gulp.dest('rev/js'));
    35 });
    36 
    37 
    38 //Html替换css、js文件版本
    39 gulp.task('revHtml', function () {
    40     return gulp.src(['rev/**/*.json', '*.html'])
    41         .pipe(revCollector())
    42         .pipe(gulp.dest('Publish'));
    43 });
    44 
    45 //拷贝除HTML外其他的文件
    46 gulp.task('copy', function(){
    47     return gulp.src([cssFile, jsFile, imageFile],{ base: '.'})
    48         .pipe(gulp.dest('Publish'));
    49 });
    50 
    51 //压缩JS
    52 gulp.task('jscompress', function(){
    53     return gulp.src(jsCompressPath)
    54         .pipe(uglify())
    55         .pipe(gulp.dest("Publish/js"));
    56 });
    57 
    58 //压缩CSS
    59 gulp.task('csscompress', function(){
    60     return gulp.src(cssCompressPath)
    61         .pipe(minifycss())
    62         .pipe(gulp.dest("Publish/css"));
    63 });
    64 
    65 //开发构建
    66 gulp.task('dev', function (done) {
    67     condition = false;
    68     runSequence(
    69         ['clean'],
    70         ['revCss'],
    71         ['revJs'],
    72         ['revHtml'],
    73         ['copy'],
    74         ['jscompress'],
    75         ['csscompress'],
    76         done);
    77 });
    78 
    79 gulp.task('clean', function(){
    80     gulp.src('rev',{read:false}).pipe(clean());
    81     return gulp.src('Publish',{read:false}).pipe(clean());
    82 });
    83 
    84 
    85 gulp.task('default', ['dev']);

    三、更改插件代码

    在项目目录下直接执行gulp命令

    $ gulp

    会得到如下效果:

    1 <link href="css/global-b40a6f2a9f.css" rel="stylesheet" type="text/css" />
    2 <script src="js/fun-3a08b5fa87.js"></script>

    需要更改gulp-rev、rev-path、gulpl-rev-collector插件的代码:

    1.node_modules/gulp-rev/index.js

    第135行:manifest[originalFile] = revisionedFile;

    更改为:manifest[originalFile] = originalFile + '?v=' + file.revHash;

    2.node_modules/rev-path/index.js

    第9行:return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`);

    更改为:return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);

    3.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];

    这里需要注意插件的版本不一样,需要改动的地方会有不同;

    本文这里所有插件的版本为:

    gulp@3.9.1
    gulp-rev@8.1.1
    gulp-rev-collector@1.2.4
    rev-path@2.0.0
    run-sequence@2.2.1
    gulp-clean@0.4.0
    gulp-minify-css@1.2.4
    gulp-uglify@3.0.0

    改完之后的效果

    1 <link href="css/global.css?v=b40a6f2a9f" rel="stylesheet" type="text/css" />
    2 <script src="js/fun.js?v=3a08b5fa87"></script>

    四、小结

    gulp的任务的执行是异步的,想要保证任务执行的顺序,需要使用run-sequence插件

     1 gulp.task('dev', function (done) {
     2     condition = false;
     3     runSequence(
     4         ['clean'],
     5         ['revCss'],
     6         ['revJs'],
     7         ['revHtml'],
     8         ['copy'],
     9         ['jscompress'],
    10         ['csscompress'],
    11         done);
    12 });

    这里顺序执行任务:

    先清除旧的rev和Pulish文件夹及其目录下所有文件(clean),之后生成CSS文件名对照映射的JSON文件(revCSS),再之后生成JS文件名对照映射的JSON文件(revJS),之后替换掉HTML中的链接,加上版本号(revHTML),将除了HTML之外其他的静态资源拷贝到Publish中(copy),然后压缩Publish/js中的JS文件,并将压缩后的文件替换掉原来的未压缩文件(jscompress),最后压缩Publish/css中的CSS文件,并替换掉未压缩文件(csscompress)。

    PS:

    1.在写路径时,"!"是排除的标识,可以排除一些文件,如:

    gulp.src(['./**/*.css', '!./node_modules/**/*'])

    这里选中的文件就是除了node_modules中的其他文件夹下的CSS文件

    2.拷贝时若要保持路径,需要加一个base选项,即:

    gulp.src('Publish/css/*.css',{ base: '.'})

     之后也可以分别对测试环境和生产环境编写任务,使用命令分开打包。

  • 相关阅读:
    我理解的优秀软件工程师
    Hello 博客园!
    线程安全与可重入函数之间的区别与联系
    linux-粘滞位的使用
    死锁产生的四个必要条件及处理死锁的策略
    数据结构—位图
    Linux下进度条的简单实现
    Linux-find命令
    Linux文件3个时间点(access time,modify time,change time)
    各种排序算法的实现、总结
  • 原文地址:https://www.cnblogs.com/Aoobruce/p/8407225.html
Copyright © 2011-2022 走看看