Skip to content

Instantly share code, notes, and snippets.

@repeatingbeats
Created April 25, 2012 05:32
Show Gist options
  • Save repeatingbeats/2486786 to your computer and use it in GitHub Desktop.
Save repeatingbeats/2486786 to your computer and use it in GitHub Desktop.
Initial thoughts on requirejs

Earlier today, I tweeted 'requirejs, why so complicated?' [1]

To add some context, I'm working on a project that involves relatively complex pipelining of static assets, and I'm investigating use of the RequireJS optimizer programmatically [2] to handle the part of the process that bundles related JS modules into bundled scripts to be passed down the pipeline for minification, fingerprinting, and deployment.

In retrospect, the answer to my flippant tweet is "because the tool solves a lot of complicated problems", but it took a while to back out from a long description of the various configuration options [3] to the options that were relevant to my problem. In particular, I felt it would have been helpful to have required options called out first, as I spent a while with a baseUrl assuming that all the js files in that dir would be optimized into the output. Instead, I got a cryptic Cannot read property '0' of undefined error.

I eventually realized that I needed to provide at least one module to optimize explicitly, and once I used the name option I was able to get a build working. Perhaps it would be helpful to have better errors for common bad input cases?

Also, as a bit of a nit on the Node.js optimize method, I think the use of a method signature that takes a callback that does not in fact appear to be invoked asynchronously is a bit confusing. Even if the underlying code is not going to use async I/O for file reading and writing, it would be more idiomatic for the callback to pass errors as the first argument instead of throwing errors. Since I'm calling the optimizer inside an async handler that is upstream of requirejs in my pipeline, I have do do something like:

var foo = function (config, callback) {

  try {
    requirejs.optimize(config, function (resp) {
      callback(null, resp);
    });
  }
  catch (e) {
    callback(e);
  }

};

If errors were passed to the callback instead of thrown by the method, that would simplify to:

var foo = function (config, callback) {
  requirejs.optimize(config, function (err, resp) {
    callback(err, resp);
  });
});

To be fair, my use case of invoking the optimizer deep inside another program instead of in a single-pass build script is probably not the typical use case.

[1] https://twitter.com/#!/repeatingbeats/status/194847966106882049

[2] http://requirejs.org/docs/node.html#optimizer

[3] https://github.com/jrburke/r.js/blob/master/build/example.build.js

@jrburke
Copy link

jrburke commented Apr 26, 2012

Thanks for the feedback. The optimization doc page was meant to show "here are the things you need to get started". Is there somewhere I could have linked to that or called it out that would have helped? Do you find it insufficient in a particular way?

I will be fixing that baseUrl by just making it optional via issue 62 which will be part of the next major requirejs release, which is the release I am working on now. I agree that is just dumb -- at the very least the error message needs to be more informative. Although, I just did a run with requirejs 1.0.8 with a build config file that had no baseUrl, and it seemed to run. Feel free to give more info about the specific use case, but no worries if you do not have time. I'll be doing more thorough testing as part of fixing 62.

On getting requirejs.optimize to use node idioms, I filed issue 156 to track that. It makes sense. I personally find the error argument first convention ugly, but when in Rome, etc... Also that call was bolted on later after the sync builder was working, so yeah the callback that is async was put there because at some point I was thinking the callback may happen async, but it is not working like that now. I can still get it to behave properly though.

Thanks for the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment