181

I have a script I am requiring from a Node.js script, which I want to keep JavaScript engine independent.

For example, I want to do exports.x = y; only if it’s running under Node.js. How can I perform this test?


When posting this question, I didn’t know the Node.js modules feature is based on CommonJS.

For the specific example I gave, a more accurate question would’ve been:

How can a script tell whether it has been required as a CommonJS module?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
theosp
  • 7,439
  • 3
  • 23
  • 24
  • 3
    I've no idea *why* you are trying to do this, but as a rule of thumb you should be using feature detection rather then engine detection. http://www.quirksmode.org/js/support.html – Quentin Nov 19 '10 at 11:44
  • 4
    This is actually a request on how to implement feature detection, but the question poorly describes itself. – monokrome Jan 23 '13 at 21:30
  • published a library for my own use, help this will help https://www.npmjs.com/package/detect-is-node – abhirathore2006 Jul 31 '16 at 06:07
  • See https://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser – brillout Oct 14 '18 at 17:48
  • One problem with the question, and most of the answers, is the assumption that there are only two possibilities: Browser or Node.js. There is a possibility that it is neither browser nor Node.js, such as the case with Oracle Java Nashorn. If the JDK is installed, the jjs command lets you run scripts. But there are many differences between Nashorn and Node.js so you can't make any assumption. And who knows what options the future may bring? Feature detection is needed. –  Mar 01 '19 at 21:47
  • @user314159 You are right. A lot of things changed in 9 years, the question made sense in the era it was posted in. – theosp Mar 28 '19 at 08:50
  • The question did not necessarily make sense even in that era 9 years ago. That is the point I am making. Even 20 years ago, there were multiple javascript engines and hosting environments. The point is that we can not make assumptions, neither in questions nor in answers. If we have explicitly stated constraints or criteria and wish to limit the domain of consideration for the sake of brevity, that is one thing. It may be valid in some circumstances. But it must be acknowledged that such a question is not complete. Otherwise we are making discussions and communities based upon bias. –  Mar 29 '19 at 11:26
  • Does this answer your question? [How to detect if script is running in browser or in Node.js?](https://stackoverflow.com/questions/34550890/how-to-detect-if-script-is-running-in-browser-or-in-node-js) – WBT Sep 29 '20 at 18:56

24 Answers24

123

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.

cezar
  • 11,616
  • 6
  • 48
  • 84
Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
  • 2
    About "Node.js is a way cleaner environment so it's unlikely that window will be declared there.": well, I just came here looking for a way to find out whether my script was running in a browser emulated by node.js + JSDOM or in a plain browser... The reason is that I have an infinite loop using setTimeout to check the URL location, which is fine in a browser, but keeps the node.js script running forever... So there might be a window in a node.js script after all :) – Eric Bréchemier Feb 01 '11 at 18:18
  • 2
    @Eric I highly doubt it will be there in the global scope, so unless you import something as `window` in the first line of your module you should not have any problems. You could also run an anonymous function and check the `[[Class]]` of `this` inside it (works only in non-strict mode) See "Class" under: http://bonsaiden.github.com/JavaScript-Garden/#typeof – Ivo Wetzel Feb 01 '11 at 18:28
  • 1
    My issue differs slightly from the OP's: I am not requiring the script, it is loaded by JSDOM with the emulated window as global context... It is still run by node.js + V8, just in a different context than usual modules. – Eric Bréchemier Feb 01 '11 at 20:01
  • @Eric Hm, you should still be able to employ the `this` trick though, since JSDOM has no way to alter the way JS works in that regard. – Ivo Wetzel Feb 01 '11 at 20:54
  • 1
    Probably... I went another direction: 1) detect support for onhashchange ("onhashchange" in window) to avoid creating the infinite loop 2) simulate support by setting the onhashchange property on emulated window in main node.js script. – Eric Bréchemier Feb 01 '11 at 22:00
  • [Edit: Replaced Comment] Thanks for the link, interesting reference :) Actually no, the Class of this does not help: the Class of window varies cross-browser, and is Object in both IE8 and the browser emulated by JSDOM+node.js (and this===window holds true in both contexts). – Eric Bréchemier Feb 02 '11 at 09:53
  • This seems to be giving me an exception: "ReferenceError: window is not defined" – B T Nov 10 '13 at 21:29
  • No way. A global variable named window being undefined is certainly NOT a guarantee that the script is not node. Far better answers below. – user3751385 Nov 29 '14 at 17:55
  • 1
    `typeof self === 'object'` might be safer since `typeof window === 'undefined'` fails on web workers scope. – Lewis May 16 '15 at 10:16
  • Yeah this doesn't work in devtool, checking "process" is the better way I reckon. – Roger Heathcote Nov 26 '16 at 13:58
82

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.

Ross
  • 14,266
  • 12
  • 60
  • 91
  • 49
    This detects CommonJS support, which browsers may support. – mikemaccana Dec 24 '12 at 14:05
  • 8
    There is a problem here and nailer "nailed it". I'm trying CommonJS in the browser, and the module loader I'm using defines module.exports, so this solution would incorrectly tell me I'm in node. – Mark Melville Dec 31 '12 at 23:02
  • 1
    @MarkMelville arguably, this is exactly what the OP is asking so therefore not a *problem*. – Ross Jan 01 '13 at 17:37
  • 13
    Poor wording on my part. I mean there is a problem with this solution. The OP may have accepted it, but I do not. – Mark Melville Jan 03 '13 at 23:40
  • 7
    This is most certainly NOT the best answer given. – user3751385 Nov 29 '14 at 17:53
  • 1
    (typeof process === 'object' && process + '' === '[object process]') is far better, as noted below. – user3751385 Nov 29 '14 at 17:59
  • tried this, was working fine on webpack-dev server...but the moment i bundled react for server rendering , things stopped working..so found and published solution https://www.npmjs.com/package/detect-is-node – abhirathore2006 Jul 31 '16 at 06:09
  • This answer is objectively wrong in 2019. Underscore can do this because adding it is just adding `_` to global exports also works in the browser. Underscore is *not* answering this question. – Jeremy Apr 25 '19 at 13:12
  • 1
    @Jeremy the OP's title that is unclear. If you read the question, the OP asks: "How can a script tell whether it has been required as a commonjs module?" and if you read the first line of my answer it states that too, in bold. I don't mind, but it is a little funny that this answer gets down votes so much. – Ross May 01 '19 at 15:15
  • 1
    @Ross I see that. I believe the title is completely clear though, and probably people who search for and read that title expect this question and answer to conform to it, and they do not. – Jeremy May 07 '19 at 12:10
58

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.

Identify Bun

(typeof process !== 'undefined') && process.isBun)

Bun is currently not implementing the full process object layout so it might be necessary to be aware of bun's current limitations in that regard.


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.

Florian Neumann
  • 5,587
  • 1
  • 39
  • 48
  • 2
    This seems to be by far the most reliable approach, thank you. Though only working for version >= 3.0.0. – filip Oct 28 '16 at 10:38
  • @daluege -- thanks for inspiration. I unfortunately didn't find a proof for lower than 0.10. – Florian Neumann Oct 28 '16 at 14:09
  • 4
    I found using react webpack, `process` and `process.version` exists within the bundle, so I added an extra check for `process.version` where `process.release.node` is undefined on client side but has a node version as a value on server side – Aaron Feb 19 '17 at 01:49
  • @Aaron: thanks for that hint. I wasn't able to find any definition of the `process.version` variable (in react, webpack or react-webpack). I would appreciate any hint where the version-variable is defined to add it to the answer. Depending in release.node constraints to node >= 3.x.x. – Florian Neumann Feb 20 '17 at 10:04
  • 2
    One-liner and safer: `function isNodejs() { return typeof "process" !== "undefined" && process && process.versions && process.versions.node; }` – brillout Oct 14 '18 at 17:49
  • I don't get it: `> typeof "process" // => 'string'` – Florian Neumann Oct 15 '18 at 17:06
  • @FlorianBreisch webpack under some circumstances can define a "mock" `process` object (which does not have `process.versions`) so your check would fail. I suggest to add an explicit check for the existence of `process.versions` and then check whether `process.versions.node` exists. – Ákos Jan 22 '20 at 13:41
  • Thank you @Ákos that's an interesting case. Can you tell me more how you use it? I'm considering adding an additional case for a mocked Node as well... – Florian Neumann Jan 23 '20 at 08:01
  • @FlorianBreisch I'm not sure how it happens exactly (i.e. who defines it). It was a vue js app that uses webpack internally I believe and it had `process` defined (but not `process.versions`). It wasn't a mocked Node, it was running in the browser. – Ákos Jan 24 '20 at 13:30
  • I see - it seems like there is node mocking enabled (see https://webpack.js.org/configuration/node/). The question now is, if that should lead to a true or false detection of Node? – Florian Neumann Jan 24 '20 at 14:53
  • @FlorianBreisch sorry didn't see your reply. I think it should be a false detection since you're not really running under Node. At least in my case that is clearly the correct answer. Anyway it's good practice to check for the existence of `process.versions` before you check for the existence of `process.versions.node` IMHO. – Ákos Feb 18 '20 at 13:23
25

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.

TimE
  • 2,800
  • 1
  • 27
  • 25
23

The following works in the browser unless intentionally,explicitly sabotaged:

if(typeof process === 'object' && process + '' === '[object process]'){
    // is node
}
else{
    // not node
}

Bam.

user3751385
  • 3,752
  • 2
  • 24
  • 24
  • 4
    var process = { toString: function () { return '[object process]'; } }; – Nick Desaulniers Dec 29 '14 at 22:46
  • 1
    Is there some reason why you use `process+''` instead of `process.toString()` ? – harmic Dec 09 '15 at 00:58
  • 3
    Almost. Use this instead: `Object.prototype.toString.call(process)` – sospedra Jan 24 '16 at 23:50
  • 2
    This is the best answer to this question. – loretoparisi Mar 10 '16 at 15:18
  • 4
    @harmic: `var process = null;` would cause the second case to fail. In both Javascript and Java, the expression `'' + x` produces the same as `x.toString()` except when `x` is nasty, the former produces `"null"` or `"undefined"` where the latter would throw an error. – joeytwiddle Jun 29 '16 at 10:20
  • This is the best solution when using `Object.prototype.toString.call(process)` instead of `process + ''` when taking `var process = { toString: function () { return '[object process]'; } };` into consideration. – Michał Pietraszko Sep 22 '16 at 11:29
17

Here's a pretty cool way to do it as well:

const isBrowser = this.window === this;

This works because in browsers the global 'this' variable has a self reference called 'window'. This self reference is not existent in Node.

  • In the browser 'this' is a reference to the global object, called 'window'.
  • In Node 'this' is a reference to the module.exports object.
    • 'this' is not a reference to the Node global object, called 'global'.
    • 'this' is not a reference to the the module variable declaration space.

To break the above suggested browser check you would have to do something like the following

this.window = this;

before executing the check.

Patrick
  • 493
  • 1
  • 6
  • 10
  • Why not simply `const isBrowser = this.window !== undefined` ? And in theory in node I can do `this.window = this` to fool the solution. – Tyler Liu May 16 '20 at 01:24
  • 1
    Great answer, but there is a caveat: this breaks in "use strict" mode. – Kithraya Oct 20 '20 at 13:27
13

Yet another environment detection:

(Meaning: most of the answers here are alright.)

function isNode() {
    return typeof global === 'object'
        && String(global) === '[object global]'
        && typeof process === 'object'
        && String(process) === '[object process]'
        && global === global.GLOBAL // circular ref
        // process.release.name cannot be altered, unlike process.title
        && /node|io\.js/.test(process.release.name)
        && typeof setImmediate === 'function'
        && setImmediate.length === 4
        && typeof __dirname === 'string'
        && Should I go on ?..
}

A bit paranoid right? You can make this more verbose by checking for more globals.

But DON'T!.

All these above can be faked/simulated anyway.

For example to fake the global object:

global = {
    toString: function () {
        return '[object global]';
    },
    GLOBAL: global,
    setImmediate: function (a, b, c, d) {}
 };
 setImmediate = function (a, b, c, d) {};
 ...

This won't get attached to the Node's original global object but it will get attached to the window object in a browser. So it'll imply that you're in Node env inside a browser.

Life is short!

Do we care if our environment is faked? It'd happen when some stupid developer declare a global variable called global in the global scope. Or some evil dev injects code in our env somehow.

We may prevent our code from executing when we catch this but lots of other dependencies of our app might get caught into this. So eventually the code will break. If your code is good enough, you should not care for each and every silly mistake that could have been done by others.

So what?

If targeting 2 environments: Browser and Node;
"use strict"; and either simply check for window or global; and clearly indicate that in the docs that your code supports only these environments. That's it!

var isBrowser = typeof window !== 'undefined'
    && ({}).toString.call(window) === '[object Window]';

var isNode = typeof global !== "undefined" 
    && ({}).toString.call(global) === '[object global]';

If possible for your use case; instead of environment detection; do synchronous feature detection within a try/catch block. (these will take a few milliseconds to execute).

e.g.

function isPromiseSupported() {
    var supported = false;
    try {
        var p = new Promise(function (res, rej) {});
        supported = true;
    } catch (e) {}
    return supported;
}
AmericanUmlaut
  • 2,817
  • 2
  • 17
  • 27
Onur Yıldırım
  • 32,327
  • 12
  • 84
  • 98
10

A one liner can be used in modern JavaScript runtimes.

const runtime = globalThis.process?.release?.name || 'not node'

The runtime value will be either node or not node.

This relies on a few newer JavaScript features. globalThis was finalized in the ECMAScript 2020 spec. Optional chaining/nullish coalescing (the ? part of globalThis.process?.release?.name) is supported in the V8 engine as of version 8.x+ (which shipped in Chrome 80 & Node 14, released on 4/21/2020).

Corey
  • 5,133
  • 3
  • 23
  • 24
8

Most of the proposed solutions can actually be faked. A robust way is to check the internal Class property of the global object using the Object.prototype.toString. The internal class can't be faked in JavaScript:

var isNode = 
    typeof global !== "undefined" && 
    {}.toString.call(global) == '[object global]';
Fabian Jakobs
  • 28,815
  • 8
  • 42
  • 39
  • 2
    This will come back true under browserify. – alt Jan 02 '14 at 06:28
  • 1
    Did you test that? I can't see how browserify can change the internal class of an object. This would require changing code in the JavaScript VM or overwriting `Object.prototype.toString` which is really bad practice. – Fabian Jakobs Jan 02 '14 at 09:54
  • I tested it. Here's what browserify does: `var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};` – Vanuan Jan 30 '14 at 15:33
  • You see, in Chrome, `({}.toString.call(window))` is equal `"[object global]"`. – Vanuan Jan 30 '14 at 15:43
  • 2
    It's strange, because `window.toString()` produces `"[object Window]"` – Vanuan Jan 30 '14 at 15:45
  • Works in Chrome Version 56.0.2924.87 (64-bit) on OSX. Guess they fixed it. – Peter Tseng Mar 22 '17 at 01:46
4

What about using the process object and checking execPath for node?

process.execPath

This is the absolute pathname of the executable that started the process.

Example:

/usr/local/bin/node

Kevin Hakanson
  • 41,386
  • 23
  • 126
  • 155
4

How can a script tell whether it has been required as a commonjs module?

Related: to check whether it has been required as a module vs run directly in node, you can check require.main !== module. http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module

Pete
  • 49
  • 1
3

Here's my variation on what's above:

(function(publish) {
    "use strict";

    function House(no) {
        this.no = no;
    };

    House.prototype.toString = function() {
        return "House #"+this.no;
    };

    publish(House);

})((typeof module == 'undefined' || (typeof window != 'undefined' && this == window))
    ? function(a) {this["House"] = a;}
    : function(a) {module.exports = a;});

To use it, you modify the "House" on the second last line to be whatever you want the name of the module to be in the browser and publish whatever you want the value of the module to be (usually a constructor or an object literal).

In browsers the global object is window, and it has a reference to itself (there's a window.window which is == window). It seems to me that this is unlikely to occur unless you're in a browser or in an environment that wants you to believe you're in a browser. In all other cases, if there is a global 'module' variable declared, it uses that otherwise it uses the global object.

kybernetikos
  • 8,281
  • 1
  • 46
  • 54
3

I'm using process to check for node.js like so

if (typeof(process) !== 'undefined' && process.version === 'v0.9.9') {
  console.log('You are running Node.js');
} else {
  // check for browser
}

or

if (typeof(process) !== 'undefined' && process.title === 'node') {
  console.log('You are running Node.js');
} else {
  // check for browser
}

Documented here

Chris
  • 4,204
  • 1
  • 25
  • 30
2
const isNode =
  typeof process !== 'undefined' &&
  process.versions != null &&
  process.versions.node != null;
BAR
  • 15,909
  • 27
  • 97
  • 185
2

From the source of debug package:

const isBrowser = typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs

https://github.com/visionmedia/debug/blob/master/src/index.js#L6

devside
  • 2,171
  • 1
  • 19
  • 23
1

This is a pretty safe and straight-forward way of assuring compatibility between server-side and client-side javascript, that will also work with browserify, RequireJS or CommonJS included client-side:

(function(){

  // `this` now refers to `global` if we're in NodeJS
  // or `window` if we're in the browser.

}).call(function(){
  return (typeof module !== "undefined" &&
    module.exports &&
    typeof window === 'undefined') ?
    global : window;
}())
ggutenberg
  • 6,880
  • 8
  • 39
  • 48
Christophe Marois
  • 6,471
  • 1
  • 30
  • 32
1

Node.js has process object, so as long as You don't have any other script which create process You can use it to determine if code runs on Node.

var isOnNodeJs = false;
if(typeof process != "undefined") {
  isOnNodeJs = true;
}

if(isOnNodeJs){
  console.log("you are running under node.js");
}
else {
  console.log("you are NOT running under node.js");
}
Dariusz Sikorski
  • 4,309
  • 5
  • 27
  • 44
0

Edit: Regarding your updated question: "How can a script tell whether it has been required as a commonjs module?" I don't think it can. You can check whether exports is an object (if (typeof exports === "object")), since the spec requires that it be provided to modules, but all that tells you is that ... exports is an object. :-)


Original answer:

I'm sure there's some NodeJS-specific symbol (EventEmitter, perhaps no, you have to use require to get the events module; see below) that you could check for, but as David said, ideally you're better off detecting the feature (rather than environment) if it makes any sense to do so.

Update: Perhaps something like:

if (typeof require === "function"
    && typeof Buffer === "function"
    && typeof Buffer.byteLength === "function"
    && typeof Buffer.prototype !== "undefined"
    && typeof Buffer.prototype.write === "function") {

But that just tells you that you're in an environment with require and something very, very much like NodeJS's Buffer. :-)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I can still break that by setting up all that stuff in a Website... that's just overkill ;) Checking for being in a Browser is easier since the Node environment is cleaner. – Ivo Wetzel Nov 19 '10 at 12:10
  • 1
    @Ivo: Yes, see my last sentence. I can just as easily break your check by defining a `window` variable within a NodeJS application. :-) – T.J. Crowder Nov 19 '10 at 12:15
  • @T.J Crowder Still Node.js is a cleaner environment it's stupid to define a window global there, and I haven't encountered something like that yet. Also you have *full* control over your Node.js code, but not over the users Browser. – Ivo Wetzel Nov 19 '10 at 12:19
  • 1
    @Ivo: I wouldn't be at *all* surprised if someone defined `window` in a NodeJS module, so they could include code that relied on `window` being the global object and didn't want to modify that code. **I** wouldn't do it, **you** wouldn't, but I bet someone has. :-) Or they've just used `window` to mean something else entirely. – T.J. Crowder Nov 19 '10 at 12:21
  • 1
    @Ivo: http://www.yuiblog.com/blog/2010/04/09/node-js-yui-3-dom-manipulation-oh-my is one reason why the window object may be defined in node.js – slebetman Nov 19 '10 at 14:35
  • @slebetman Just tested YUI3 it does *not* leak into the global namespace, would you please test stuff before posting comments? – Ivo Wetzel Nov 19 '10 at 15:09
  • 1
    @T.J.Crowder `typeof process !== "undefined" && process.title === "node"` – Raynos Apr 17 '12 at 09:49
0

This does not directly answer your question, as you wanted to check for Node.js specifically, however it's useful enough to warrant saying:

Most of the time, if you just want to distinguish between browsers and server-side javascript, it's enough to just check for the existence of a document.

if (typeof document !== 'undefined') {} // do stuff

// This one is overkill, but 100% always works:
if (typeof window !== 'undefined' && window && window.window === window) {
   if (typeof window.document !== 'undefined' && document.documentElement) {

   }
}
Kithraya
  • 358
  • 2
  • 10
0

You can use getters to detect when your module.exports is read and that would mean that it was required.

let required = false;

function myFunction() {
  // your code whatever
  return required;
}

if (typeof module == 'object') {
  Object.defineProperty(module, 'exports', {
    get: () => {
      required = true;
      return myFunction;
    }
  })
}

Tested in my console on Chrome Version 106.0.5249.119 (Official Build) (x86_64) and Node v16.15.0

LuisAFK
  • 846
  • 4
  • 22
0
const isNode = ({}).toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
Newbie...
  • 139
  • 2
  • 16
-1

Very old post, but i just solved it by wrapping the require statements in a try - catch

try {
     var fs = require('fs')
} catch(e) {
     alert('you are not in node !!!')
}
shitpoet
  • 419
  • 5
  • 11
  • 3
    That's not true, you can use browserify to use "nodeish" require() calls – fat Jan 11 '15 at 21:06
  • also, when requiring a module, node (if it's node) has to look for it in all of the `node_modules` folders it knows and then open the module file, read it and run it, which can take some time – LuisAFK Oct 24 '22 at 14:49
-1

Very old post, but I solved with a combination of the other answers:

var isNode=()=>!("undefined"!=typeof window||"object"!=typeof module||!module.exports||"object"!=typeof process||!process.moduleLoadList);
console.log(isNode()); //=> false
Nirvana
  • 405
  • 3
  • 15
-2

Take the source of node.js and change it to define a variable like runningOnNodeJS. Check for that variable in your code.

If you can't have your own private version of node.js, open a feature request in the project. Ask that they define a variable which gives you the version of node.js that you're running in. Then check for that variable.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 1
    That again doesn't solve his (basically unsolvable) problem, I can again just create such a variable in the Browser. Better way would be to prevent scripts from creating a `window` global, guess I gonna file a feature request on that one. – Ivo Wetzel Nov 19 '10 at 12:52
  • @Ivo: That's a bad idea that would break code that uses jsdom (https://github.com/tmpvar/jsdom) to do server side dom manipulation using familiar libraries like YUI and jQuery. And there are code currently in production that does this. – slebetman Nov 19 '10 at 14:39
  • @slebetman No it will not break jsdom. I'm speaking of *global*, like in **no var statement global**, the example code there uses the `var` statement, people who just leak it into the global namespace, well they don't get the concept of self-contained modules then – Ivo Wetzel Nov 19 '10 at 15:03
  • @Ivo that's kind of violent, it's like saying we should take the ability to eat cakes because people get fat overeating them. You *must* clutter the global namespace to achieve a library that will work inter-module. Or you could wrap it all up in a single module, but then what's the point? – Ben Barkay Apr 10 '13 at 08:13
  • @IvoWetzel Can't you just use strict mode then? – Nirvana May 21 '21 at 00:39