The Universal Module Definition is an extremely useful addition to an IIFE.
Cross Compatible IIFE
When I built gopher, my pub/sub messaging system, I wanted it to work in both the browser and as a node module. After a bit of googling and reading I found the perfect solution: the Universal Module Definition (UMD). UMD supplements the standard IIFE pattern with some simple type checking to determine how the module should be injected into the global namespace.
Node.js uses the CommonJS require() method to import modules from an exported source. This doesn't work well in the browser without a bit of hacking. Asynchronous Module Definitions (AMDs) are a simple modular pattern for creating a namespace-safe in-browser application, but this requires an external library like RequireJS. The UMD pattern can allow for both.
The Universal Module Definition
UMD is a modification of the IIFE pattern that allows for a conditional declaration of the object to export. The key to the UMD pattern is utilizing the function-expression part of the IIFE to conditionally determine the namespace endpoint(s) for the module.
// Universal Module Definition IIFE
(function(global, appName, app) {
// define() the module using AMD/RequireJS
if (typeof define === "function" && typeof define.amd === "object")
define(app);
// Export as a node or CommonJS module
else if (typeof module !== "undefined") module.exports = app(global);
// Add the app to the global browser namespace
else global[appName] = app(global);
})(this, "App", function(global) {
"use strict";
// Define the functions here
function _appDoThis() {} // Private
function getThis() {} // Public
// Return the functions that you want to be publicly accessible
return {
getThis: getThis
};
});
The logic of the UMD is simple:
- If 'define' exists as a function, then add the app using the AMD/RequireJS define() method
- If the 'module' object exists, then assign the app definition to module.exports for node or CommonJS.
- Otherwise we will assume this is a browser, so just add it to the global namespace
Conclusion
The UMD pattern is a fantastic way to utilize IIFE in a way that maximizes the flexibility of your application deployment while also creating a safely scoped environment for your code.