Skip to content

Instantly share code, notes, and snippets.

@spadgos
Created November 22, 2013 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spadgos/7597842 to your computer and use it in GitHub Desktop.
Save spadgos/7597842 to your computer and use it in GitHub Desktop.
/*
Below is an incomplete snippet of code which is used to implement the Lazy Require Calls
method described here http://spadgos.github.io/rupy13/#/29
Basically, it takes an AST like this:
var Foo = require('foo');
function bar() {
Foo.quux();
}
...into this:
var Foo;
function bar() {
(Foo || (Foo = require('foo'))).quux();
}
The `ASTHelpers.transform` method is simply a wrapper for the standard Uglify transform,
which executes the callback only on nodes which match the given `type`. Hopefully it
should be understandable enough.
*/
// Get the AST subtree to perform a lazy require call. Basically converts a reference to a variable which has been
// required into `variable || (variable = require("path/to/require"))`
function getReplacementRequireVar(name, req) {
var miniAST = uglify.parse(uglify.string_template('{name} || ({name} = require("{req}"))', {
name: name,
req: req
}));
// miniAST.body == [ SimpleStatement ]
return miniAST.body[0].body;
}
// see if this symbol is the same as the one defined at the top of the file
function matches (symbolDec) {
return symbolDec.start === this.start;
}
/**
* Finds all variables assigned to a require call and rewrites them to only make the call to require when necessary.
*/
function rewriteRequires(ast) {
var map = {};
ASTHelpers.transform(ast, [{
type: 'VarDef',
handler: function (node) {
if (node.value
&& node.value instanceof uglify.AST_Call
&& node.value.expression.name === 'require'
&& node.value.expression.global()) {
map[node.name.name] = {
module: node.value.args[0].value,
node: node
};
node.value = null; // delete the require call
}
}
}]);
ASTHelpers.transform(ast, [{
type: 'SymbolRef',
handler: function (node) {
var reqInfo = map[node.name];
if (reqInfo && node.thedef.orig.some(matches, reqInfo.node)) {
return getReplacementRequireVar(node.name, reqInfo.module);
}
}
}]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment