I'm trying out Grunt and need a simple way to concatenate my modules

This is my first time using Grunt and I'd like to have it combine all my js modules, each of which is wrapped in an immediately executing function, containing a 'use strict' declaration and put them into one file, wrapped up in only one immediately executing function, with only one 'use strict' declaration.

How is this normally done?

I figured this would be a common use case? Perhaps I'm going about things the wrong way? Should I be using one of the module loading formats (i.e. commonjs, amd) All these files will always be loaded together in the browser, so I actually wouldn't mind removing all the immediately executing functions if that's how people normally go about it. The important part is that the end result is somehow wrapped, passes lint and unit tests and contains the 'use strict' declaration.

(I should clarify, I do have it working, linting, unit-testing, concatenating, and minifying, it just feels like I'm doing something wrong when I see a bunch of unnecessary immediately executing functions in the final concatenated file.)

Answers:

Answer

I usually do it like the jQuery team does it. You create an intro.js and outro.js and put everything else in between:

intro.js

;(function( window, undefined ){
  'use strict';

outro.js

}( window ));

grunt.js:

concat: {
  dist: {
    src: [
      'js/src/intro.js',
      ...
      'js/src/outro.js'
    ],
    dest: 'js/out/app.js'
  }
}
Answer

As of pull request 10, grunt-contrib-concat now has a footer option. Instead of an intro and an outro file, I would use a banner and a footer.

Gruntfile.js

concat: {
  dist: {
    src: ['src/my-lib.js'],
    dest: 'dist/<%= pkg.name %>.js',
    options: {
      banner: ";(function( window, undefined ){ \n 'use strict';",
      footer: "}( window ));"
    }
  }
}

In my opinion, this is more maintainable and allows for templating using other properties defined in your Gruntfile.

Answer

Just want to add to @elclanrs answer that if you want to be able to keep your modules in separate files for easier debugging during development, you would obviously have to wrap them with intro.js and outro.js as well. Using the built-in concat task you'd have to write something like:

concat: {
  events_debug: { // wrap the 'events' module in IIFE
    src: [
      'js/src/intro.js',
      'js/src/events.js',
      'js/src/outro.js'
    ],
    dest: 'js/out/events.js'
  },
  callbacks_debug: { // wrap the 'callbacks' module in IIFE
    src: [
      'js/src/intro.js',
      'js/src/callbacks.js',
      'js/src/outro.js'
    ],
    dest: 'js/out/callbacks.js'
  }

  // zzZZZ...
}

Which is very tedious and self-repeating. Perhaps you may want to create a custom task for mass-wrapping files, e.g.

wrap: {
    html: {
        intro: 'partials/intro.js',
        outro: 'partials/outro.js',
        src: 'js/*.js',
        dest: 'out' // output directory
    }
}

There was a question about this recently, see this thread:

Using grunt concat, how would I automate the concatenation of the same file to many other files?

Answer

I would recommend you to use my grunt plugin grunt-concat-deps since it automatically resolves your modules independent on your architecture.

PLUS: You don't need any explicit module configuration for the plugin as it relies on declarative and decentralized module definition in a YUIDoc style.

See here for further information: https://github.com/leoselig/grunt-concat-deps

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.