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

By Destin Moulton on March 22, 2017

    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.