Skip to content

Instantly share code, notes, and snippets.

@jrburke
Created December 1, 2011 19:07
Show Gist options
  • Save jrburke/1419063 to your computer and use it in GitHub Desktop.
Save jrburke/1419063 to your computer and use it in GitHub Desktop.
Multiple single file builds using one "build script" for requirejs optimizer
//Load the requirejs optimizer
var requirejs = require('./path/to/r.js'),
//Set up basic config, include config that is
//common to all the optimize() calls.
basConfig = {
baseUrl: './some/path',
paths: {
//whatever is neded globally.
}
};
// Function used to mix in baseConfig to a new config target
function mix(target) {
for (var prop in basConfig) {
if (basConfig.hasOwnProperty(prop)) {
target[prop] = basConfig[prop];
}
}
return target;
}
//Now do a series of builds of individual files, using the args suggested by:
//http://requirejs.org/docs/optimization.html#onejs
requirejs.optimize(mix({
name: 'first/main/module',
include: [/*if you need to include extra modules */],
out: 'path/to/output/firstMain-built.js'
}), function (buildReportText) {
//First build complete, start the next one.
requirejs.optimize(mix({
name: 'second/main/module',
include: [/*if you need to include extra modules */],
out: 'path/to/output/secondMain-built.js'
}), function (buildReportText) {
//all done.
});
});
@jrburke
Copy link
Author

jrburke commented Dec 1, 2011

This is a file that would be run in Node. Also, I have not explicitly tested this, but it is expected to work. If it does not, then it is probably a bug I should fix.

@jwhitley
Copy link

jwhitley commented Dec 5, 2011

I note that the calls to optimize bomb out on r.js 1.0.2 with:

TypeError: undefined is not a function
    at /Users/whitley/src/requirejs-rails/bin/r.js:9009:17

It looks like the invocation of the callback function parameter should be optional in the definition of optimize. Or is there some contractual obligation re: callback that I'm missing.

@jrburke
Copy link
Author

jrburke commented Dec 7, 2011

@jwhitley, thanks for doing a pull request to fix the error with a missing callback.

In that pull request, I think we want to emphasize the optimization could complete async in the future, so I'll update the gist to reflect that.

@jwhitley
Copy link

jwhitley commented Dec 8, 2011

That's fine. In that case I'd switch this code around to define an array of spec objects, ala { name: 'foo', ... } then run them like so:

var specs = [spec1, spec2, spec3];  // assume specN's defined previously, elided for clarity

var async_runner = specs.reduceRight(function(prev, curr) {
  return function (buildReportText) { 
    requirejs.optimize(curr, prev);
  };
}, function(buildReportText) {} );

async_runner();

Is chaining definitely going to be the New World Order for this API? If so, I'll go ahead and switch my r.js driver generator around right now.

@jrburke
Copy link
Author

jrburke commented Dec 9, 2011

So that reduceRight will create an array of functions, each one, when called, will run a build. For me the magic part is still what async_runner() does. I feel like there is something missing from this code sample, something that steps through the functions in async_runner?

Is chaining definitely going to be the New World Order for this API? If so, I'll go ahead and switch my r.js driver generator around right now.

Yes, r.js will likely need to go to callback-based, async processing for the file issues, so if it is easier to switch now, then probably for the best. I do not expect to get to the async file IO issues until after 1.0.3. I may even wait for a 1.1.

@jwhitley
Copy link

jwhitley commented Dec 9, 2011

reduceRight will create an array of functions

Not quite; this usage of reduceRight creates a function, actually a chain of nested functions, from an array of simple objects (the first parameters to requirejs.optimize). Note: I forgot to include the call to mix in my example above; let's just assume it's already been map'ped onto the spec objects. Expanding what my snippet would do, it'll create a function, async_runner, whose definition looks like this:

// Expansion of the reduceRight() call

var async_runner = function (buildReportText) {
  requirejs.optimize(spec1, function (buildReportText) {
    requirejs.optimize(spec2, function (buildReportText) {
      requirejs.optimize(spec3, function (buildReportText) {});
    });
  });
}

Knowing that we don't actually use the buildReportText parameter on the outermost function, we can invoke the whole nested mess with a call like async_runner().

This approach rather cleanly abstracts the interesting core data (here, a sequence of input parameters) from the rather hairy code that consumes that data.

@jwhitley
Copy link

jwhitley commented Dec 9, 2011

James, check out this gist for a little example that you can run in node to play with this idea.

@jwhitley
Copy link

jwhitley commented Dec 9, 2011

Thanks for the heads-up. requirejs-rails on the precompilation branch has been updated for this change. See rjs_driver.js.erb on the branch.

@jrburke
Copy link
Author

jrburke commented Dec 9, 2011

@whitley, neat use of reduceRight, thanks for the explanation. Nice approach to know in general for repeated async calls.

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