As the CTO, I have to make choices for the foundation of the site.. but like everyone else, sometimes we make mistakes and it takes too long to figure out, and you have to take the decision to continue down the rabbit hole, or GTFO of it ASAP.

Instead of crying on my own and defending my bad choice, I will explain my opinions in a series of blog posts. I hope there’s only going to be a very few of them.. I also hope it can help you in the future.

Today, we’re going to talk about the Javascript loader that I decided to use, RequireJS

RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

This post will be a pretty long one; to really understand the downside of RequireJS, you need to see the whole package. Some parts might be confusing if you never used RequireJS, just comment below and I’ll add some more details.

When I started coding and made the folder structure for RequireJS, everything was rainbows and unicorns. From a development point of view, it’s seriously awesome. You just require the file, and it works in the browser. Modify the file, refresh, changes are there! Magic. It only includes the files you need.

My philosophy was always to be developer friendly. Code should be easy to code, easy to read and understand, easy to deploy.

RequireJS fits into easy to code, easy to read and understand.. but everything breaks when it comes to deploying.

You need to ‘shim’

We need jQuery. We also need jQuery plugins. Want to make both works? Use shim.

And then you can use it like this.

define(["jquery", "jquery.alpha", "jquery.beta"], function($) {
    //the jquery.alpha.js and jquery.beta.js plugins have been loaded.
    $(function() {

Okay seems simple enough.. Just a couple of config file changes. Let’s continue coding.

Your folder structure needs to be revamped

Your site is done. Wohoo! Let’s put it on staging and see how it goes… Dynamic loading is a cool idea.. but terrible in execution.

Let’s take an example: cameraguyalex.

That’s 82 javascript files getting used in there. You either have the choice of making a script for that page, or loading a ton of small scripts.., or assemble them!

Of course, the answer to this is to assemble them.. but then, out of those 82 scripts, 30~ of them are globally used. It would make sense to make 2 files, a common script files, and a page-specific file.

So… how do we achieve that with r.js? RequireJS has this example.

If you want to use shim config, for instance to load Backbone, see the requirejs/example-multipage-shim example instead. This project will not work well with shim config. This project works best when all the dependencies are AMD modules.

So if we want to use common scripts, and at the same time use shim, we have to change our whole folder structure, and use this one.

This is the proposed structure:



require(['common'], function () {


define(function (require) {
    var $ = require('jquery');

    // homepage logic goes here

Yep, you have 1 file that feels really redundant.. and you have to have them for each pages.

Not only that, but this syntax is not usable anymore:

define(["jquery", "jquery.alpha", "jquery.beta"], function($) {
    //the jquery.alpha.js and jquery.beta.js plugins have been loaded.
    $(function() {

If you had the bad luck of coding before trying to deploy (like me!), you’ll have a bad day. Instead, you have to use them like this:

define(function($) {
    var $ = require('jquery');

And you also have to put this for each page, in your gruntfile.

    name: 'about',
    include: ['app/about'],
    exclude: ['common']

So.. 1 new page means 1 extra file and an extra grunt config. Okay.

If it works on the dev, it doesn’t mean it will work in production. Also: forget bower.

So now we hacked up our structure and code to make it work in a bundled/shim scenario. Cool.

But, as the title says: It doesn’t always work. This is a killer.

There’s primarily 3 reasons it failed:

  1. I forgot to include the jquery plugin, but I used it in another module so it’s loaded in the dev environment.
  2. For some reason, shims doesn’t always work.
  3. I forgot to include it in the gruntfile.

The first and third reason is a human mistake, okay.

The second reason is a real head banger. I thought shim was supposed to work?

The solution: wrap every plugin with this:

define(function(require) {
    var jQuery = require('jquery');
    var $ = jQuery;

    // plugin goes here

Sometimes you’ll be lucky and the plugin dev will use UMD. If not, tough luck. I don’t take chances anymore, so I just wrap them all.

You still need that require.js

Even though you “compiled” everything into 2 files, you still need that requirejs. It’s an extra 10kb.. and no, you can’t use almond because we have 2 files and almond only works with a very specific scenario.


There’s a few more downside that I omitted since it’s very specific to us (like ReactJS server rendered templates).

So.. should you use RequireJS? I have no idea, but it’s definitely not for us. A large web app needs a build system anyway, so might as well take a loader that had that in mind.

What to do from here? I’ll probably take a weekend and convert everything to Browserify. I’ve heard good things about it.

If you have any comments or questions, please hit us up below. If you think I’m doing something wrong, definitely please hit us up below.

Here’s a proof of concept on github:



Reddit user tbranyen helped me out. It seems like I have do an inline recursive nested require calls for it to work properly, ensuring that the common file is loaded first. It works! I’m still wary of it, and will probably not use requirejs in my next project, but it’s nice to see a solution to one of the problem.

About author View all posts Autor website

Makara Sok

Makara Sok

Mak is the master of our stack and the company joker. When he’s not striving to be the architect of the sweetest code, he’s busy telling tales of his soapy adventures.

  • minlo

    What is the context for your shim config not working? I’ve had plenty of issues with require.js, and am certainly not in love with it, but I’ve always been able to resolve them(possible headbanging required) I use it in the context of a multi-page app, reduce it with r.js and deploy it via grunt. nnEDIT: Just to clarify I ask because I’ve had similar issues with Shims, but again have always been able to resolve them with help from the documentation.

    • Makara Sok

      Badly written jQuery plugins that uses both $ and jQuery variables, or uses global variables. The kicker is that it’s inconsistent. Sometimes it works, sometimes it doesn’t. Seems like a race condition of whether they get loaded before or something. nnEither way, they get resolved when I wrap them around within the define tags. nnHonestly, I shouldn’t be trying to resolve. RequireJS is wasting too much time tinkering stuff that should be working. Just trying to make r.js work with grunt took wayyy too much time.

      • Tim Branyen

        This is completely bogus. jQuery exports itself globally as both jQuery and $ and when you load using shim they work 100% correctly with any plugin.

        • Makara Sok

          I like your assertion that it works with ANY plugin, as if you’ve tested all of them. nnn I remove the define wrap around that plugin, and only shim it in config, it doesn’t work. nnn I wrap it around define, it works. =|.

          • Tim Branyen

            My assertion is based on the fact that I wrote the initial shim implementation and that was the whole point and stated goal.

    • ngDeveloper

      Probably why the call it ‘Require’, because handbanging against wall is “required” lol.

  • Alex V

    Not sure how you have shim issues. when compiled, it just defines a variable, in order of deps, and then returns that global inside a define. Inconsistencies with jQuery should not affect anything as stated in a prior comment. Now that Backbone and Underscore are AMD, the shim definitely gets smaller, and easier to manage.nnYou’re right, RequireJS isn’t for everything, but it is nice to use in complex web apps I build everyday. It was a struggle to get used to it at first, but once understood, it’s a life saver. One of the coolest things we’ve implemented in the stuff I work on is accessing global variables between iframes. Not monumental, but holy hell does it make my life easier

    • Makara Sok
    • Makara Sok

      I called it wrong, Tim corrected me. My page specific scripts loaded before my common. It somehow worked in dev, but not when bundled. nnnI think requireJS is better than using old school-nothing, but I’ll definitely be looking out for an alternative for my next project. nnnCheers and thanks for your comment.

      • Alex V

        No worries, I’ll take a look at your link. Learn something new everyday! Good article by the way. I’m really looking forward to the ES6 loader. Once it comes out, the only thing standing in my way would be IE (stupid IE)

  • Tim Branyen

    With regards to the edit, the require calls are not recursive, they are nested. You should not be wary of this, since you are already doing this.

    • Makara Sok

      I worded it poorly. I’m wary of using requirejs for my next project. For, I’ll continue using it since I just learned of your fix, but this is probably the last time I will. nnnThanks for your comments, cheers.

      • Tim Branyen

        No worries, glad I could help!

  • Shripad Krishna

    I know its late but try Webpack:

  • Arash Shakery

    I’ve had such difficulties, a bigger problem is when you want to share code between node.js and client. Even thought these can be solved with more configurations, I prefer a more natural solution. After some days googling, i guess i have found a solution:

    • Makara Sok

      This is one of my most recent pains. Since we use React, we wanted to pregenerate the DOM on the server side.. but it doesn’t play well with requirejs. It’s a headache 🙂

  • ngDeveloper

    That about summarizes my experience with require.js and a big app. Having used Browserify now, what is your impressions on that? Is Browserify modular, or is it just for concatenating down to a single file…?

  • Dustan Kasten

    I realize I’m pretty late to the game on this, but we had a number of projects at work go down the AMD rabbit hole (and we also use React). To rectify this I spent a couple afternoons creating this AMD -> CJS converter.

    It doesn’t cover all of AMD’s methods or shim converting, but it should be able to get you 90% of the way there.

    • Makara Sok

      That’s awesome! I’ll give it a try once we’re ready to move to CJS.

      • Dustan Kasten

        Cool. Definitely ping me or leave an issue on github if you have any snags using it in your conversion process.

  • Gerard Sans

    What’s with the white source background? Just from the things you mention I can tell you these are not RequireJS issues but maybe missunderstandings. Once I can read the code I will tell you =)

    • Makara Sok

      I fixed the white source issue. The update for the WP Theme broke it for some reason.

      They are indeed RequireJS and R.js issues, but feel free to tell me if you think otherwise.

      I have already replaced the whole codebase to Webpack + CommonJS. The different is amazing, I’m never going back.

      • Gerard Sans

        Cool. Now I can see! =) I think, these issues can be solved by using the right RequireJS setup. If you can create a simple skeleton in Plunkr I can try to do it for you. Have a nice day!

        • Makara Sok

          We already moved away from RequireJS, and that’s exactly one of the problem. “With the right requireJS setup”. Depending on what you do, there’s different setups and there’s too many different setups.