• 使用gulp解决RequireJS项目前端缓存问题(一)


    1、前言

    使用gulp解决RequireJS项目前端缓存问题(一)

    使用gulp解决RequireJS项目前端缓存问题(二

     

    前端缓存一直是个令人头疼的问题,你有可能见过下面博客园首页的资源文件链接:

    有没有发现文件名后面有一串不规则的东东,没错,这就是运用缓存机制,我们今天研究的就是这种东西。

    先堵为快,猛戳链接下载Demohttps://github.com/hua126mail/gulpRequireJsCache

    以dist为根目录,运行http://localhost/html/index.html,如果出现“Good!成功加载index.js”,则表示成功了。

    不熟悉gulp的同学,可以参考这个比较详细的教程:http://www.ydcss.com/archives/18

    不熟悉RequireJS的同学,可以参考官方教程:http://www.requirejs.cn/

    2、项目主要目录:

      gulpRequireJsCache
      |
      |-- dist          //存放发布的文件
      |
      |-- rev          //存放控制版本号的 rev-manifest.json
      |
      |-- src          //项目源文件
      |
      |-- gulpfile.js     //gulp主文件,定义的任务都在这里
      |
      |-- package.json    //gulp依赖包配置文件
      |
      |-- landing.html

      根据执行命令npm install --save-dev后,主目录下会多一个node_modules文件夹,至此,gulp基本配置完成。

      gulpfile文件:
    var gulp = require('gulp'),
        sass = require('gulp-sass'),                        //编译sass
        cssmin = require('gulp-clean-css'),                    //压缩css
        autoprefixer = require('gulp-autoprefixer'),        //添加浏览器前缀
        rev = require('gulp-rev'),                            //添加版本号
        revCollector = require('gulp-rev-collector'),        //添加版本号
        clean = require('gulp-clean'),                        //清理文目标文件夹
        csso = require('gulp-csso'),                        //合并css属性
        csslint = require('gulp-csslint'),                    //css语法检查
        csscomb = require('gulp-csscomb'),                    //css 样式表的各属性的顺序
        imagemin = require('gulp-imagemin'),                //图片压缩
        cache = require('gulp-cache'),                        //缓存处理
        htmlmin = require('gulp-htmlmin'),                    //压缩html
        replace = require('gulp-replace'),                    //替换路径
        uglify = require('gulp-uglify'),                    //压缩js
        jshint = require('gulp-jshint')                        //js语法检查
    ;
    
    gulp.task("cleanCss",function(){
        return gulp.src('dist/css',{read:false})
        .pipe(clean());
    });
    
    gulp.task('sass', ['cleanCss'],function () {            //执行完cleanCss任务后再执行sass任务
          gulp.src('src/sass/**/*.scss')
        .pipe(sass())
        .pipe(cssmin())
        .pipe(autoprefixer())
        //.pipe(csscomb())
        .pipe(csso())
        .pipe(csslint())
        .pipe(rev())
        .pipe(gulp.dest('dist/css'))
        .pipe(rev.manifest())//- 生成一个rev-manifest.json
        .pipe(gulp.dest('rev/css'));
        
    });
    
    gulp.task("cleanImg",function(){
        return gulp.src('dist/img',{read:false})
        .pipe(clean());
    });
    
    gulp.task('imgmin',['cleanImg'], function () {
        gulp.src('src/img/**/*.{png,jpg,gif,ico}')
            .pipe(cache(imagemin()))                        //没有修改的图片直接从缓存文件读取
            .pipe(rev())
            .pipe(gulp.dest('dist/img'))
            .pipe(rev.manifest())//- 生成一个rev-manifest.json
            .pipe(gulp.dest('rev/img'));
    });
    
    gulp.task("cleanJs",function(){
        return gulp.src(['dist/js/*','!dist/js/lib'],{read:false})
        .pipe(clean());
    })
    
    gulp.task('jsmin', ['cleanJs'], function () {
        gulp.src(['src/js/**/*.js','!src/js/**/*.min.js'])
            .pipe(jshint())
            .pipe(uglify())
            .pipe(rev({merge:true}))
            .pipe(gulp.dest('dist/js'))
            .pipe(rev.manifest())//- 生成一个rev-manifest.json
            .pipe(gulp.dest('rev/js'));
            
        gulp.src(['src/js/lib/**/*.js'])
            .pipe(gulp.dest('dist/js/lib'))
    });
    
    gulp.task('htmlmin',function () {
        var options = {
            removeComments: true,//清除HTML注释
            //collapseWhitespace: true,//压缩HTML
            removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
            minifyJS: true,//压缩页面JS
            minifyCSS: true//压缩页面CSS
        };
        gulp.src('src/html/**/*.html')
            .pipe(htmlmin(options))
            .pipe(rev())
            .pipe(gulp.dest('dist/html'))
            .pipe(rev.manifest())//- 生成一个rev-manifest.json
            .pipe(gulp.dest('rev/html'));
    });
    
    
    gulp.task('replaceURL', function(){
        gulp.src(['dist/html/**/*.html'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/html'));
            
        gulp.src(['dist/css/**/*.css'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/css'));
            
        gulp.src(['dist/js/**/*.js'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/js'));
        
    });
    
    gulp.task('revUrl', function() {
        gulp.src(['rev/{css,img,js}/*.json', 'dist/html/**/*.html'])        //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe(revCollector())                               //- 执行文件内css名的替换
        .pipe(gulp.dest('dist/html'));    //- 替换后的文件输出的目录
        
        gulp.src(['rev/{css,img,js}/*.json', 'dist/css/**/*.css'])        //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe(revCollector())                               //- 执行文件内css名的替换
        .pipe(gulp.dest('dist/css'));    //- 替换后的文件输出的目录
        
        gulp.src(['rev/{css,img,js}/*.json', 'dist/js/**/*.js'])        //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe(revCollector())                               //- 执行文件内css名的替换
        .pipe(gulp.dest('dist/js'));    //- 替换后的文件输出的目录
        
    });
    
    gulp.task("autowatch",function(){
        gulp.watch(['src/sass/**/*.scss'],['sass']);        //监听sacc文件改变后,编译、去缓存
    });
    
    
    /*
     *    单步步骤:
     *     1.gulp sass                    编译scss文件
     *     2.gulp jsmin                压缩js
     *     3.gulp imgmin                压缩图片
     *     4.gulp htmlmin                压缩HTML文件
     *     5.gulp replaceURL            替换相对路径为绝对路径
     *     6.gulp revUrl                引用manifest给HTML添加版本号
     *     
     * 
     *     gulp sass jsmin htmlmin imgmin replaceURL revUrl
     * 
     * 
     * 
     * 如果改了scss文件:则执行:gulp sass
     * 如果改了js文件:则执行:gulp jsmin
     * 如果改了img文件:则执行:gulp imgmin
     * 
     * 只要改了HTML引用到的资源文件,最后都需要执行gulp htmlmin,gulp replaceURL,gulp revUrl,以清理缓存
     * */
    View Code

    根据最后的单步步骤,我们来一步步解剖说明:

    var gulp = require('gulp'),
        sass = require('gulp-sass'),                        //编译sass
        cssmin = require('gulp-clean-css'),                    //压缩css
        autoprefixer = require('gulp-autoprefixer'),        //添加浏览器前缀
        rev = require('gulp-rev'),                            //添加版本号
        revCollector = require('gulp-rev-collector'),        //添加版本号
        clean = require('gulp-clean'),                        //清理文目标文件夹
        csso = require('gulp-csso'),                        //合并css属性
        csslint = require('gulp-csslint'),                    //css语法检查
        csscomb = require('gulp-csscomb'),                    //css 样式表的各属性的顺序
        imagemin = require('gulp-imagemin'),                //图片压缩
        cache = require('gulp-cache'),                        //缓存处理
        htmlmin = require('gulp-htmlmin'),                    //压缩html
        replace = require('gulp-replace'),                    //替换路径
        uglify = require('gulp-uglify'),                    //压缩js
        jshint = require('gulp-jshint')                        //js语法检查
    ;

    这些都是执行任务时要用到的插件,看注释大概就知道是干嘛的了。

     

     2.1、css相关处理:运行“gulp sass”

    gulp.task("cleanCss",function(){
        return gulp.src('dist/css',{read:false})
        .pipe(clean());
    });
    
    gulp.task('sass', ['cleanCss'],function () {            //执行完cleanCss任务后再执行sass任务
          gulp.src('src/sass/**/*.scss')
        .pipe(sass())
        .pipe(cssmin())
        .pipe(autoprefixer())
        //.pipe(csscomb())
        .pipe(csso())
        .pipe(csslint())
        .pipe(rev())
        .pipe(gulp.dest('dist/css'))
        .pipe(rev.manifest())//- 生成一个rev-manifest.json
        .pipe(gulp.dest('rev/css'));
        
    });

    gulp.task("autowatch",function(){
      gulp.watch(['src/sass/**/*.scss'],['sass']); //监听sacc文件改变后,编译、去缓存
    });

    因为公司项目用的是sass,所以加了一个监听任务,去编译生成css文件,css发生更改之后先执行“cleanCss”任务,清空dist文件夹下的css文件,重点是后面的.pipe(rev.manifest()),这一步将生成一个资源文件路径的rev-manifest.json文件,里面的内容是这样的:

    {
      "base/base.css": "base/base-c1e638e1f6.css",
      "controller/index.css": "controller/index-1454781768.css"
    }

    没错,这是用来最后在HTML文件替换css引用路径的。

    同时,dist/css目录下也生成对应的文件:

    2.2、img相关处理:运行“gulp imgmin”

    gulp.task("cleanImg",function(){
        return gulp.src('dist/img',{read:false})
        .pipe(clean());
    });
    
    gulp.task('imgmin',['cleanImg'], function () {
        gulp.src('src/img/**/*.{png,jpg,gif,ico}')
            .pipe(cache(imagemin()))                        //没有修改的图片直接从缓存文件读取
            .pipe(rev())
            .pipe(gulp.dest('dist/img'))
            .pipe(rev.manifest())//- 生成一个rev-manifest.json
            .pipe(gulp.dest('rev/img'));
    });

    过程就不多说啦,一样的先清空dist的图片文件夹,压缩图片,生成rev-manifest.json,生成的文件如下:

    {
      "push-bg.jpg": "push-bg-6179117417.jpg"
    }

       

    2.3、js相关处理:运行“gulp jsmin”

    gulp.task('jsmin', ['cleanJs'], function () {
        gulp.src(['src/js/**/*.js','!src/js/**/*.min.js'])
            .pipe(jshint())
            .pipe(uglify())
            .pipe(rev({merge:true}))
            .pipe(gulp.dest('dist/js'))
            .pipe(rev.manifest())//- 生成一个rev-manifest.json
            .pipe(gulp.dest('rev/js'));
            
        gulp.src(['src/js/lib/**/*.js'])
            .pipe(gulp.dest('dist/js/lib'))
    });

    过程就是检查语法,压缩,生成rev-manifest.json,要注意的地方是min类型的文件是放在lib目录下,是不需要压缩处理的,直接拷贝过去即可。生成的rev-manifest.json文件如下:

    {
      "base/cal.js": "base/cal-2e41f44581.js",
      "base/require-config.js": "base/require-config-3c5aeda076.js",
      "controller/index.js": "controller/index-d14ed3eca8.js"
    }

     

     2.4、js相关处理:运行“gulp htmlmin”

    gulp.task('htmlmin',function () {
        var options = {
            removeComments: true,//清除HTML注释
            //collapseWhitespace: true,//压缩HTML
            removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
            minifyJS: true,//压缩页面JS
            minifyCSS: true//压缩页面CSS
        };
        gulp.src('src/html/**/*.html')
            .pipe(htmlmin(options))
            .pipe(rev())
            .pipe(gulp.dest('dist/html'))
    });

    过程省略一百字。。。

     

     2.5、替换相对路径:运行“gulp replaceURL”

    gulp.task('replaceURL', function(){
        gulp.src(['dist/html/**/*.html'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/html'));
            
        gulp.src(['dist/css/**/*.css'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/css'));
            
        gulp.src(['dist/js/**/*.js'])
            .pipe(replace('../css', '/css'))
            .pipe(replace('../js', '/js'))
            .pipe(replace('/src', '/dist'))
            .pipe(gulp.dest('dist/js'));
        
    });

    过程就是替换所有文件的相对路径为绝对路径。

    2.6、替换资源文件引用(重中之重):运行“gulp revUrl”

    gulp.task('revUrl', function() {
        gulp.src(['rev/{css,img,js}/*.json', 'dist/html/**/*.html'])        //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe(revCollector())                                               //- 执行文件内css名的替换
        .pipe(gulp.dest('dist/html'));                                        //- 替换后的文件输出的目录
        
        gulp.src(['rev/{css,img,js}/*.json', 'dist/css/**/*.css'])        
        .pipe(revCollector())                               
        .pipe(gulp.dest('dist/css'));    
        
        gulp.src(['rev/{css,img,js}/*.json', 'dist/js/**/*.js'])        
        .pipe(revCollector())                               
        .pipe(gulp.dest('dist/js'));    
        
    });

     

    3、测试结果:

    打开dist/html/index.html

    <!doctype html>
    <html>
        <head>
            <title>requirejs</title>
            <meta charset="utf-8">
            <link rel="stylesheet" type="text/css" href="/css/base/base-c1e638e1f6.css">
            <link rel="stylesheet" type="text/css" href="/css/controller/index-1454781768.css">
            <!--[if IE]>
                <link rel="stylesheet" type="text/css" href="/csstest/main.css"/>
            <![endif]-->
        </head>
        <body>
            <div class="main border-grey" id="name1">
                <div class="wrapper">未加载 index.js</div>
            </div>
            
            
            <script type="text/javascript" src="/js/base/require-config-3c5aeda076.js" defer="true"></script>
            <script data-main="/js/controller/index-d14ed3eca8.js" src="/js/lib/require.min.js" defer="true"></script>
        </body>
    </html>

    可以看到,css和js文件引用的路径都替换成了相应rev-manifest.json中的值。

    访问一下页面:

    控制台也显示资源文件引用正常:

    3.1、修改测试

    修改base.scss中body{font-size: 14px;}的字体为20px,重新执行gulp,再截图看下控制台:

    可以发现,除了base.css引用变了之外,其他保持不变。

    4、补充:

    按上面的步骤走完,gulp已经满足项目基本需要了,但仍存在两点问题:

    1. 对通过require-config.js引入的js文件修改后,没有更新到
    2. 每次gulp运行完后都会生成新的文件,开发环境是做了清除dist目录处理,但对于一般公司服务器而言,发布到生产环境上,不可能每次发布都对dist做清空处理,文件只会越积越多
    3. 咦,怎么跟前言博客园截图引用的方法不一样。。。

    上面这3点,将在下一节中详解。

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    欢迎转载,转载请注明作者:飘飞的夏秋 和出处 http://www.cnblogs.com/chenchenghua/p/5953767.html

  • 相关阅读:
    Java GC机制详解
    程序员面试的时候如何谈薪酬待遇?
    每个程序员都会遇到的面试问题:谈谈进程和线程的区别
    面试问题:你了解Java内存结构么(Java7、8、9内存结构的区别)
    UVa 208
    山科 STUST OJ Problem B: 编写函数:String to Double (II) (Append Code)
    山科SDUST OJ Problem J :连分数
    辗转相除法
    [比赛总结]ACM div3 G 比赛总结
    SDUST OJ Problem G 动态的字符串排序
  • 原文地址:https://www.cnblogs.com/chenchenghua/p/5953767.html
Copyright © 2020-2023  润新知