notoriousb1t

Transition to RequireJS

For months I had been teetering on the fence about whether or not my team should use RequireJS:  an Asynchronous Module Definition (AMD) system that is popular for separating JavaScript into neat, clean modules.

Here were some of my fears concerns:

  1. Will this take more than a few days to retrofit existing code?
  2. Will this cause performance issues in our Apache Cordova mobile apps?
  3. Will the framework be unnecessarily restrictive?
  4. Will my developers adapt to it?

How did you use it?

index.html

<script src="assets/lib/require.min.js" data-main="assets/config.js"></script>  

We included the script tag below to load the library, and we set the data-main attribute to the file name where we configured our application once RequireJS was loaded.

assets/config.js

    require.config({
        baseUrl: 'assets/lib',
        paths: {
            app: '../app',
            jquery: 'jquery.min.js'
        },
        /// ...
    });
    requirejs(['app/main']);

In the config.js file we needed to define the base url for each module and dependency, and configure an explicit path for modules that were not along that base url.

The path 'jquery' combined with the baseUrl told RequireJS that it could find the jquery module at 'assets/lib/jquery.min.js' on the server.  The app folder was next to the lib folder in assets ('assets/app/'), so we had set an explicitly path for it as well up one directory.

The last line instructed RequireJS to fetch and execute the module at 'assets/app/main.js'.  This file served as our entry point into the actual application.

assets/app/main.js:

    define(function(require, exports, module) {
        // import jquery
        var $ = require('jquery');

        $(document).ready(function(){
            // do something with elements
        });
    });

Each file was wrapped in a call to the define function.  It accepted a function with require, exports, and module as the names of the parameters.

The require parameter was used to import other modules and the exports parameter was used to export a property from other modules.

Inside of the function, we added our imports at the top.  In the example, we imported jQuery to variable $ and then used the document ready feature in jQuery to do some work on code.

That setup lead to very nice looking code.  We were able to do away with shims and instead use custom code organized into modules.

Fortunately, everything worked out nicely:

  1. It took 6 hours to convert a mobile application with 40 views from our home-brew namespace based code
  2. Performance is about the same; no loading issues have been found
  3. The framework helped shape our code rather than box it in.  Using the CommonJS syntax, we were able to split apart unrelated code and identify duplicate code.  It helped us find places where responsibilities were mixed.
  4. My team instantly loved Require.js.  The CommonJS syntax is easy on the eyes and was a quick transition even for my server-oriented developers. Because of its structure, I was able to start easing them into developing Cordova app.

Overall, using this library was a boon for us in taming our mobile apps.