Blog // UMD: One IIFE Pattern To Rule Them All

JavaScript Promise API

By on

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.