I am writing a 3rd party JS app using requireJS and I want to keep the global namespace clean of everything but the single global interface object that will be created by my app. I haven't had any problems with this except for requireJS.
As an option to the optimizer, require.js can be rolled into the build and namespace can be defined make the optimizer scope all references to require functions to that namespace.
eg. require(...) becomes my_scope.require(...)
The problem is that this global namespace object won't exist until it gets created in the app. The optimizer ensures that requireJS loads & executes before any of the code that it loads, so when it comes time for a require function to execute (like require or define), an exception is thrown (the namespace object is undefined).
Has anyone successfully made this happen without manually altering the built script or running another script separate of and prior to the built script? In other words, is there a proper way to achieve this?
For anyone else who has been searching for the answer to this question, here it is, found in a pile of used elbow grease.
In the build config options, forget about using namespace
. There is a property "wrap" that allows you to wrap the entire build script in code of your choosing.
Simply define it as the following to create a local scope around everything (including requireJS functions):
require.config({
wrap: {
start: "(function() {",
end: "}());"
}
})
My take is that requirejs, and module loaders in general, have a different approach to reducing global clutter than namespacing. With require, you do not need to attach things to the global namespace, just use a require method call within a closure to get locally scoped references.
So, you trade off a single bit of global clutter (i.e. window.require) for all the other things you'd need to attach.
In a namespaced implementation, you would use something like
var foo = window.my_scope.foo.bar
With module loaders, you'd use a call to require. In the case of a CommonJS module loader, you'd do something like this
var foo = require("my_scope/foo/bar")
RequireJs adds a little more complexity to this because it's an AMD module loader, but that's another whole conversation unto itself!