JavaScript library compatible with RequireJs, jQuery and Node.js

When you’re updating an open-source JavaScript library, one of the biggest challenges is making sure it works everywhere your users want it to. I recently spent an evening updating my is_email validation library to make it universally compatible across Node.js, RequireJS (AMD), and standard browser environments using jQuery.

While looking for the best way to do this, I noticed the documentation was scattered all over the place. I had to piece together snippets from several different blogs just to get a clear picture. To save you the headache, I’ve pulled all that information together into this single, practical guide.

Step 1: Encapsulating the Library (The IIFE)

First, we want to prevent our library from polluting the global scope. By wrapping our code inside an IIFE (Immediately Invoked Function Expression), we keep our helper functions completely private, exposing only what we explicitly want to share.

For this guide, we’ll use a simple function that checks if a variable is undefined:

JavaScript
(function () {
    function is_undefined(variable) {
        return typeof variable === 'undefined';
    }
})();

Step 2: Adding RequireJS (AMD) Support

To make the library compatible with Asynchronous Module Definition (AMD) loaders like RequireJS, we check if the global define function exists and has the define.amd property. If it does, we register our module:

JavaScript
(function () {
    function is_undefined(variable) {
        return typeof variable === 'undefined';
    }

    // Support RequireJS / AMD
    if (typeof define === 'function' && define.amd) {
        define(function() { 
            return is_undefined; 
        });
    }
})();

Step 3: Adding Node.js (CommonJS) Support

Next, we want developers to be able to require() our file seamlessly in Node.js. We can detect a Node/CommonJS environment by checking if the module and exports objects are available:

JavaScript
(function () {
    function is_undefined(variable) {
        return typeof variable === 'undefined';
    }

    // Support Node.js / CommonJS
    if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') {
        module.exports = is_undefined;
    }
})();

Step 4: Adding jQuery Support

Finally, if the user is loading our script directly in a traditional browser environment alongside jQuery, we can attach our utility directly to the jQuery global object.

Depending on how you want developers to use your utility, you have two options:

JavaScript
(function () {
    function is_undefined(variable) {
        return typeof variable === 'undefined';
    }

    // Support jQuery
    if (typeof jQuery !== 'undefined') {
        // Option A: Use it globally as a utility function like $.is_undefined(x)
        jQuery.is_undefined = is_undefined;

        // Option B: Attach it to a collection selector like $('div').is_undefined()
        jQuery.fn.is_undefined = function() {
            // Inside the function, 'this' refers to the selected jQuery elements
            return is_undefined(this.val()); 
        };
    }
})();

Putting It All Together: A Universal Pattern

By combining these environment checks, we create a truly universal script that dynamically adapts to wherever it gets executed—whether that’s a backend server or a frontend script loader.

A live, production example of this exact pattern can be found in my is_email library, which handles robust RFC-compliant email validation.

Hopefully, having this pattern altogether in one place saves you some time on your next open-source project. If you have any suggestions, edge cases to add, or questions about the implementation, let’s write down in the comments!

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.