JavaScript is used in many different environments, and each environment has its own method for deploying modules. Some allow importing objects into a local namespace, but notably web browsers do not. So, what is the best way to write a module that can be safely deployed across different environments? Anonymous closure module pattern My example [...]
JavaScript is used in many different environments, and each environment has its own method for deploying modules. Some allow importing objects into a local namespace, but notably web browsers do not. So, what is the best way to write a module that can be safely deployed across different environments?
Anonymous closure module pattern
My example module will be implemented as an anonymous closure. It will have one public class and a private member.
(function () {
var PublicClass = function () {};
var PrivateMember = new Object();
})();
I will incrementally add support for each environment by detecting whether that environment is present.
Web browsers
Web browsers do not support importing into a local namespace, so I simply add PublicClass to the global window namespace.
(function () {
var PublicClass = function () {};
var PrivateMember = new Object();
if (typeof(window) !== 'undefined') {
// browser
window.PublicClass = PublicClass;
}
})();
Client must first include the module with a script HTML tag.
<script type="text/javascript" src="sample-module.js"></script>
<script type="text/javascript">
var instance = new PublicClass();
</script>
CommonJS
CommonJS is a pattern implemented by some server-side JavaScript engines such as Node and Narwhal. In this model, a module assigns its public interface to a special exports object.
(function () {
var PublicClass = function () {};
var PrivateMember = new Object();
if (typeof(window) !== 'undefined') {
// browser
window.PublicClass = PublicClass;
} else if (typeof(exports) !== 'undefined') {
// commonjs
exports.PublicClass = PublicClass;
}
})();
Clients require the module, which returns the module’s exports.
var PublicClass = require('./sample-module').PublicClass;
var instance = new PublicClass();
JavaScriptCore
JavaScriptCore (or “jsc”) does not follow the CommonJS pattern. Instead, when a file is included with the load function, the last value in the file is returned to the caller.
I return an object literal from the anonymous function which simulates the exports object in CommonJS. Since the anonymous function is executed as the last statement in the file, the exports are returned to the client. This case doesn’t rely on any special variable such as window or exports, so I will make it default rather than detecting the JavaScriptCore environment.
(function () {
var PublicClass = function () {};
var PrivateMember = new Object();
if (typeof(window) !== 'undefined') {
// browser
window.PublicClass = PublicClass;
} else if (typeof(exports) !== 'undefined') {
// commonjs
exports.PublicClass = PublicClass;
} else {
// jsc (default)
return {
"PublicClass": PublicClass
};
}
})();
Clients load the module, which returns the module’s exports.
var PublicClass = load('sample-module.js').PublicClass;
var instance = new PublicClass();
Why not use a global variable?
There is another JavaScript module pattern that declares a global variable to contain the module’s public interface, as in this example.
var PublicClass = (function () {
var PublicClass = function () {};
var PrivateMember = new Object();
return PublicClass;
})();
This pattern will work perfectly in web browsers and JavaScriptCore, but it also pollutes JavaScriptCore’s global namespace. Since JavaScriptCore supports local imports, global variables should be avoided. Furthermore, this pattern does not support multiple public interfaces, e.g., a single anonymous closure that exports two public classes.
Example: GraphJS
GraphJS is a JavaScript module of mine that uses the module deployment pattern I described. It works with Node, Narwhal, Ringo, JSC, and in web browsers.
I recently grew quite frustrated when I had to update Emend’s Twitter bot to use OAuth. There are, of course, readily available implementations of OAuth in python, even some specifically engineered for App Engine with lovely persistence and caching and KILL ME NOW. I gave up after a couple hours of staring at this nonsense. [...]
I recently grew quite frustrated when I had to update Emend’s Twitter bot to use OAuth.
There are, of course, readily available implementations of OAuth in python, even some specifically engineered for App Engine with lovely persistence and caching and KILL ME NOW.
I gave up after a couple hours of staring at this nonsense. I grew so displeased because my app doesn’t need 95% of what these libraries offer. I only need to sign requests with a fixed oauth_consumer_key, oauth_consumer_secret, oauth_token, and oauth_token_secret. However, this simple task would require me to subclass or instantiate several object with Culver’s library, and I can’t even begin to fathom what I’d need to do with Knapp’s offering.
(Aside: if you want to authorize and build access tokens for your app, I highly recommend this excellent OAuth test client)
I finally teased apart the core function of signing requests, thanks in large part to the great reference example. If all you need is to access a protected resource, this will get the job done with a single function call, no object-orientation required.
There are a couple posts out there that discuss stripping tags with html5lib, but they seem intent on preserving the “acceptable elements” such as <span> and <code>. This is fine unless you really want to friggin’ strip out the tags, like I needed for Emend. The following is my solution. Source code for stripping tags [...]
There are a couple posts out there that discuss stripping tags with html5lib, but they seem intent on preserving the “acceptable elements” such as <span> and <code>.
This is fine unless you really want to friggin’ strip out the tags, like I needed for Emend. The following is my solution.
Source code for stripping tags with html5lib and unit test.
For example,
>>> from strip_tags import strip_tags
>>> strip_tags('<p>foo</p> <script>bar</script>')
u'foo bar'
Thanks go to Edward O’Connor for pointing me towards html5lib in the first place. It’s a huge improvement over HTMLParser.