Cachebusting using grunt for multiple js files

2019-07-30 04:00发布

问题:

There are several questions on SO for grunt / cachebusting but I didn't find anything close enough to what I'm looking for. Hence, a new question..

Here is what I'm looking for. My Backbone/Marionette app's JS files are organized into module level folders.

|- app

|- modules
   |- module1
     |- scripts
        |- models
        |- views
        |- templates
   |- module2
     |- scripts
        |- models
        |- views
        |- templates
|- index.html
|- scripts
    |- app.js
|- styles

What I need is a way to concatenate / minify / uglify all of module1 into its own single file (say module1.min.js). Then that file should be versioned and references to module1 in other JS files (in other modules) to be updated accordingly. That way, I can have the modules downloaded to client only when the corresponding functionality is invoked from client, while still getting benefits of caching and cache busting. This helps avoid the costly download if I were to concatenate all js files for the entire app into a single file.

Is there any solution for that?

I did like the answer from developer JBCP in this thread - Prevent RequireJS from Caching Required Scripts

However, it involves tweaking the requirejs library itself, which my client isn't too inclined to do (for obvious reasons).

I use grunt for builds and so, I looked at grunt tasks - concat, usemin, rev. And I use requireJS in the app. But I can't find a solution for updating the references to module1 in js files from other modules, I'm stuck. Looking for solution for this issue or alternate approaches for building module level min.js files along with cachebusting.

Any help is greatly appreciated.

Thanks, DJ

回答1:

To concatenate, use "grunt-contrib-concat".

To minify and uglify JavaScript files, use "grunt-contrib-uglify".

To cache bust:

1) use "grunt-cache-busting" - it rename both the file and reference in the html with md5 hash of the file.

2) If you want to append custom string to file name,

you can use "grunt-text-replace" or "grunt-cache-breaker" to rename the reference in the html file.

you can use "grunt-contrib-copy" to rename the file name.

Ex:-

module.exports = function (grunt) {
    var timeStamp;

    // Project configuration.
    grunt.initConfig({
copy: {            
            rename: {
                files: [
                    {
                        expand: true,
                        dot: true,
                        cwd: 'js/',
                        dest: 'dist/js/',
                        src: [
                            '*.*'
                        ],
                        rename: function (dest, src) {
                            return dest + src.replace('.js','.' + timeStamp + '.js');
                        }
                    }
                ]
            }
},
replace: {

            bust: {
                src: ['dist/*.html'],
                overwrite: true,                 // overwrite matched source files
                replacements: [
                    {
                        from: '.js',

                        to: function () {
                            timeStamp = new Date().getTime() ;
                            return '.' + timeStamp + '.js';
                        }
                    }
                ]
            }
        }
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-text-replace');

To remove origional files - use "grunt-contrib-clean". You may want to use another "copy" tasks for this.

For reference: my default task. grunt.registerTask('default', ['clean', 'copy:dist', 'replace','copy:rename','clean:old', 'copy:after','clean:after']);