How to check whether a script is running under Node.js?

Solution 1:

Well there's no reliable way to detect running in Node.js since every website could easily declare the same variables, yet, since there's no window object in Node.js by default you can go the other way around and check whether you're running inside a Browser.

This is what I use for libs that should work both in a Browser and under Node.js:

if (typeof window === 'undefined') {
    exports.foo = {};

} else {
    window.foo = {};
}

It might still explode in case that window is defined in Node.js but there's no good reason for someone do this, since you would explicitly need to leave out var or set the property on the global object.

EDIT

For detecting whether your script has been required as a CommonJS module, that's again not easy. Only thing commonJS specifies is that A: The modules will be included via a call to the function require and B: The modules exports things via properties on the exports object. Now how that is implement is left to the underlying system. Node.js wraps the module's content in an anonymous function:

function (exports, require, module, __filename, __dirname) { 

See: https://github.com/ry/node/blob/master/src/node.js#L325

But don't try to detect that via some crazy arguments.callee.toString() stuff, instead just use my example code above which checks for the Browser. Node.js is a way cleaner environment so it's unlikely that window will be declared there.

Solution 2:

By looking for CommonJS support, this is how the Underscore.js library does it:

Edit: to your updated question:

(function () {

    // Establish the root object, `window` in the browser, or `global` on the server.
    var root = this; 

    // Create a reference to this
    var _ = new Object();

    var isNode = false;

    // Export the Underscore object for **CommonJS**, with backwards-compatibility
    // for the old `require()` API. If we're not in CommonJS, add `_` to the
    // global object.
    if (typeof module !== 'undefined' && module.exports) {
            module.exports = _;
            root._ = _;
            isNode = true;
    } else {
            root._ = _;
    }
})();

Example here retains the Module pattern.

Solution 3:

I currently stumbled over a wrong detection of Node which is not aware of the Node-environment in Electron due to a misleading feature-detection. The following solutions identify the process-environment explicitly.


Identify Node.js only

(typeof process !== 'undefined') && (process.release.name === 'node')

This will discover if you're running in a Node-process, since process.release contains the "metadata related to the current [Node-]release".

After the spawn of io.js the value of process.release.name may also become io.js (see the process-doc). To proper detect a Node-ready environment i guess you should check as follows:

Identify Node (>= 3.0.0) or io.js

(typeof process !== 'undefined') &&
(process.release.name.search(/node|io.js/) !== -1)

This statement was tested with Node 5.5.0, Electron 0.36.9 (with Node 5.1.1) and Chrome 48.0.2564.116.

Identify Node (>= 0.10.0) or io.js

(typeof process !== 'undefined') &&
(typeof process.versions.node !== 'undefined')

@daluege's comment inspired me to think about a more general proof. This should working from Node.js >= 0.10. I didn't find a unique identifier for prior versions.


P.s.: I am posting that answer here since the question lead me here, although the OP was searching for an answer to a different question.

Solution 4:

The problem with trying to figure out what environment your code is running in is that any object can be modified and declared making it close to impossible to figure out which objects are native to the environment, and which have been modified by the program.

However, there are a few tricks we can use to figure out for sure what environment you are in.

Lets start out with the generally accepted solution that's used in the underscore library:

typeof module !== 'undefined' && module.exports

This technique is actually perfectly fine for the server side, as when the require function is called, it resets the this object to an empty object, and redefines module for you again, meaning you don't have to worry about any outside tampering. As long as your code is loaded in with require, you are safe.

However, this falls apart on the browser, as anyone can easily define module to make it seem like it's the object you are looking for. On one hand this might be the behavior you want, but it also dictates what variables the library user can use in the global scope. Maybe someone wants to use a variable with the name module that has exports inside of it for another use. It's unlikely, but who are we to judge what variables someone else can use, just because another environment uses that variable name?

The trick however, is that if we are assuming that your script is being loaded in the global scope (which it will be if it's loaded via a script tag) a variable cannot be reserved in an outer closure, because the browser does not allow that. Now remember in node, the this object is an empty object, yet, the module variable is still available. That is because it's declared in an outer closure. So we can then fix underscore's check by adding an extra check:

this.module !== module

With this, if someone declares module in the global scope in the browser, it will be placed in the this object, which will cause the test to fail, because this.module, will be the same object as module. On node, this.module does not exist, and module exists within an outer closure, so the test will succeed, as they are not equivalent.

Thus, the final test is:

typeof module !== 'undefined' && this.module !== module

Note: While this now allows the module variable to be used freely in the global scope, it is still possible to bypass this on the browser by creating a new closure and declaring module within that, then loading the script within that closure. At that point the user is fully replicating the node environment and hopefully knows what they are doing and is trying to do a node style require. If the code is called in a script tag, it will still be safe from any new outer closures.