Combining Modules in Require.js

Here’s a quick tip that I learned today the hard way, because it’s actually in the documentation.

In one of my projects, I’ve got a bunch of commands that I want to attach to an event based on what menu item is selected.  My app object listens for menu events and then wires up the command based on the selected menu item.  My first version looked like this:

define ['EventEmitter','ResizeCommand','RotateCommand'],(event_emitter,resize,rotate) ->

This is module definition is obviously going to get very messy as I add more available commands.  The solution was to create a new module to combine all of the commands and use a different variation on the module definition, where you’re only dependency is require itself.

define (require) ->
  {
    resize: require 'ResizeCommand'
    rotate: require 'RotateCommand'
  }

Now I can simplify my app module to look like this

define ['EventEmitter','Commands'],(event_emitter,commands) ->
  class App
    constructor: (@canvas_element) ->
      event_emmitter.on "Toolbar.MenuItemSelected", (command_name) ->
      @onClickHandler = commands[command_name].action

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Clark Pan

    Do you know well this works with the optimizer? Would it optimize those modules into the Commands module?

    • John Teague

      It doesn’t inline them, if that’s what you mean.  It does combine them in one file however.

      I ran r.js with this configuration:
      ({    baseUrl: “.”,   
      paths:{
      “jquery”: “jquery-1.7.2.min”,
      “underscore”: “underscore-min”,
      “jqueryUI”: “jqueryui-min”,
      “bootstrap”: “bootstrap”,
      “EventEmitter2″: “eventemitter2″,
      “kinetic”: “kinetic-min”,
      “sylvester”: “sylvester”
      },
          name: “commands”,
          out: “commands-built.js”
      })

      And it included the resize module and the rotate module in the commands-built.js class, along with all of the other required external files.

      It does however convert the require statements to the array of dependencies.  This is the output for that file.

      define(“commands”,["require","ResizeCommand","rotate"], function(e){
      return{
      resize:e(“ResizeCommand”),
      rotate:e(“rotate”)
      }
      })

      This is described in the documentation as a necessary step, since some older browsers do not support the function calls they using during runtime.  Refer to the documentation link in the post to read more about it.

      • Clark Pan

        That looks about right. I don’t think the optimiser could inline those modules as then you wouldn’t be able to reuse them in other parts of the application.

        Thanks for the tip.