Question

  1. Can I instruct Grunt to concatenate all JS files defined in index.html without specifically naming them?
  2. Can Grunt also create new index.html file that will load the concatenated JS file instead of the previous multiple files?
  3. Can Grunt also uglify the JS file at a same time?
  4. Can Grunt do this not only for JS files but also CSS files used in a given html file?

I spent significant time googling but the Grunt ecosystem seems to be so fragmented and so unfamiliar to me :(.

PS: I have decided to use Grunt because there is direct integration in WebStorm 8 but maybe other tool would be more suitable for this task?

Was it helpful?

Solution

There are many different solutions available which is why it seems fragmented. I'll describe a couple of the seemingly popular methods.

  1. Use grunt-usemin
    You specify blocks within your HTML that it reads and feeds to your other Grunt tasks (concat, uglify, etc). Their docs have extensive examples to handle a lot of different scenarios.

  2. Use a module bundler such as grunt-webpack, grunt-browserify or grunt-contrib-requirejs
    Instead of adding script tags to your HTML, use a require() syntax to include files when needed. Which, depending on the method, will add the scripts to your page or bundle into a single file. These methods only require including, usually, a single javascript file.

Explore and figure out which solution makes the most sense for your needs.

OTHER TIPS

I solved this problem by adding this function at the top of my Gruntfile:

var isCssRegex = /^\s*<\s*link.*href=["']([^"']*)["'].*$/i;
var isJsRegex = /^\s*<\s*script.*src=["']([^"']*)["'].*$/i;
var extractJsRegex = /src\s*=\s*"(.+?)"/
var extractCssRegex = /href\s*=\s*"(.+?)"/

function extractFilenames(src, type) {
    var filenames = [];
    var data = require('fs').readFileSync(src, 'utf8');
    var lines = data.replace(/\r\n/g, '\n').split(/\n/);
    var webContent = require('path').dirname(src);

    lines.forEach(function (line) {
        if (line.match(type === 'css' ? isCssRegex : isJsRegex)) {
            var src = line.match(type === 'css' ? extractCssRegex : extractJsRegex)[1];
            filenames.push(webContent + '/' + src);
        }
    });

    return filenames;
};

Then in my concat task, I can do this:

concat: {
    js: {
        src: extractFilenames('src/main/resources/public/index.html', 'js'),
        dest: 'build/app.js'
    },

    css: {
        src: extractFilenames('src/main/resources/public/index.html', 'css'),
        dest: 'build/style.css'
    }
},
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top