Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I instruct Grunt to concat all JS files defined in index.html?

  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?

like image 367
daniel.sedlacek Avatar asked Jun 03 '14 15:06

daniel.sedlacek


2 Answers

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.

like image 72
Kyle Robinson Young Avatar answered Sep 22 '22 20:09

Kyle Robinson Young


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'
    }
},
like image 42
Adam Avatar answered Sep 19 '22 20:09

Adam