Wie überprüfe ich, ob ein Skript unter Node.js ausgeführt wird?

159

Ich habe ein Skript, das ich von einem Node.js-Skript benötige, um die JavaScript-Engine unabhängig zu halten.

Zum Beispiel möchte ich exports.x = y;nur tun , wenn es unter Node.js läuft. Wie kann ich diesen Test durchführen?


Beim Posten dieser Frage wusste ich nicht, dass die Node.js- Modulfunktion auf CommonJS basiert .

Für das spezifische Beispiel, das ich gegeben habe, wäre eine genauere Frage gewesen:

Wie kann ein Skript feststellen, ob es als CommonJS-Modul erforderlich war?

theosp
quelle
3
Ich habe keine Ahnung, warum Sie dies versuchen, aber als Faustregel sollten Sie die Funktionserkennung anstelle der Motorerkennung verwenden. quirksmode.org/js/support.html
Quentin
4
Dies ist eigentlich eine Anfrage zur Implementierung der Feature-Erkennung, aber die Frage beschreibt sich selbst schlecht.
Monokrom
veröffentlichte eine Bibliothek für meinen eigenen Gebrauch, Hilfe dies hilft npmjs.com/package/detect-is-node
abhirathore2006
Ein Problem mit der Frage und den meisten Antworten ist die Annahme, dass es nur zwei Möglichkeiten gibt: Browser oder Node.js. Es besteht die Möglichkeit, dass es sich weder um einen Browser noch um Node.js handelt, wie dies bei Oracle Java Nashorn der Fall ist. Wenn das JDK installiert ist, können Sie mit dem Befehl jjs Skripts ausführen. Es gibt jedoch viele Unterschiede zwischen Nashorn und Node.js, sodass Sie keine Annahme treffen können. Und wer weiß, welche Optionen die Zukunft bringen kann? Funktionserkennung ist erforderlich.

Antworten:

80

Wenn Sie nach CommonJS-Unterstützung suchen , geht die Bibliothek Underscore.js folgendermaßen vor :

Bearbeiten: zu Ihrer aktualisierten Frage:

(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._ = _;
    }
})();

Beispiel hier behält das Modulmuster bei.

Ross
quelle
45
Dadurch wird die CommonJS-Unterstützung erkannt, die möglicherweise von Browsern unterstützt wird.
Mikemaccana
7
Hier gibt es ein Problem und der Nagler hat es "genagelt". Ich versuche CommonJS im Browser und der von mir verwendete Modullader definiert module.exports, sodass diese Lösung mir fälschlicherweise mitteilt, dass ich im Knoten bin.
Mark Melville
1
@ MarkMelville wohl, genau das ist es, was das OP verlangt, also kein Problem .
Ross
13
Schlechte Formulierung meinerseits. Ich meine, es gibt ein Problem mit dieser Lösung. Das OP hat es vielleicht akzeptiert, aber ich nicht.
Mark Melville
7
Dies ist mit Sicherheit NICHT die beste Antwort.
user3751385
107

Nun, es gibt keine zuverlässige Möglichkeit, das Ausführen in Node.js zu erkennen, da jede Website problemlos dieselben Variablen deklarieren kann. Da windowNode.js jedoch standardmäßig kein Objekt enthält, können Sie umgekehrt vorgehen und prüfen, ob Sie in a ausgeführt werden Browser.

Dies ist, was ich für Bibliotheken verwende, die sowohl in einem Browser als auch unter Node.js funktionieren sollten:

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

} else {
    window.foo = {};
}

Es kann immer noch explodieren, falls dies windowin Node.js definiert ist, aber es gibt keinen guten Grund für jemanden, dies zu tun, da Sie vardie Eigenschaft für das globalObjekt explizit weglassen oder festlegen müssten .

BEARBEITEN

Um festzustellen, ob Ihr Skript als CommonJS-Modul benötigt wurde, ist dies wiederum nicht einfach. CommonJS gibt lediglich an, dass A: Die Module über einen Aufruf der Funktion aufgenommen werden requireund B: Die Module exportieren Dinge über Eigenschaften des exportsObjekts. Wie das nun implementiert wird, bleibt dem zugrunde liegenden System überlassen. Node.js verpackt den Inhalt des Moduls in eine anonyme Funktion:

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

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

Aber versuchen Sie nicht , das über verrückte arguments.callee.toString()Dinge zu erkennen , sondern verwenden Sie einfach meinen Beispielcode, der oben nach dem Browser sucht. Node.js ist eine viel sauberere Umgebung, daher ist es unwahrscheinlich, dass windowsie dort deklariert wird.

Ivo Wetzel
quelle
2
Über "Node.js ist eine viel sauberere Umgebung, daher ist es unwahrscheinlich, dass dort ein Fenster deklariert wird.": Nun, ich bin gerade hierher gekommen, um herauszufinden, ob mein Skript in einem von node.js + JSDOM emulierten Browser ausgeführt wurde oder in einem einfachen Browser ... Der Grund ist, dass ich eine Endlosschleife habe, die setTimeout verwendet, um den URL-Speicherort zu überprüfen, was in einem Browser in Ordnung ist, aber das Skript node.js für immer laufen lässt ... Es könnte also ein Fenster geben Immerhin in einem node.js-Skript :)
Eric Bréchemier
1
@Eric Ich bezweifle sehr, dass es im globalen Bereich vorhanden sein wird. Wenn Sie also nichts wie windowin der ersten Zeile Ihres Moduls importieren, sollten Sie keine Probleme haben. Sie könnten auch eine anonyme Funktion und überprüfen Sie die laufen [[Class]]von seinem thisInneren (funktioniert nur in nicht-Strict - Modus) Siehe „Klasse“ unter: bonsaiden.github.com/JavaScript-Garden/#typeof
Ivo Wetzel
1
Mein Problem unterscheidet sich geringfügig von den OPs: Ich benötige das Skript nicht, es wird von JSDOM mit dem emulierten Fenster als globalem Kontext geladen ... Es wird weiterhin von node.js + V8 ausgeführt, nur in einem anderen Kontext als die üblichen Module.
Eric Bréchemier
1
Wahrscheinlich ... Ich bin in eine andere Richtung gegangen: 1) Erkennen der Unterstützung für onhashchange ("onhashchange" im Fenster), um das Erstellen der Endlosschleife zu vermeiden. 2) Simulieren der Unterstützung durch Festlegen der Eigenschaft onhashchange für das emulierte Fenster im Skript "main node.js".
Eric Bréchemier
1
typeof self === 'object'Dies ist möglicherweise sicherer, da der typeof window === 'undefined'Umfang der Web-Worker fehlschlägt.
Lewis
45

Ich bin derzeit über eine falsche Erkennung von Knoten gestolpert, die aufgrund einer irreführenden Funktionserkennung die Knotenumgebung in Electron nicht kennt . Die folgenden Lösungen identifizieren die Prozessumgebung explizit.


Identifizieren Sie nur Node.js.

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

Dadurch wird festgestellt, ob Sie in einem Knotenprozess ausgeführt werden, da dieser process.releasedie "Metadaten zur aktuellen [Knoten-] Version" enthält.

Nach dem Spawn von io.jsprocess.release.name kann auch der Wert von werden io.js(siehe Prozessdokument ). Um eine knotenbereite Umgebung richtig zu erkennen, sollten Sie Folgendes überprüfen:

Identifizieren Sie den Knoten (> = 3.0.0) oder io.js.

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

Diese Aussage wurde mit Node 5.5.0, Electron 0.36.9 (mit Node 5.1.1) und Chrome 48.0.2564.116 getestet.

Identifizieren Sie den Knoten (> = 0,10,0) oder io.js.

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

Der Kommentar von @ daluege hat mich dazu inspiriert, über einen allgemeineren Beweis nachzudenken. Dies sollte ab Node.js> = 0.10 funktionieren . Ich habe keine eindeutige Kennung für frühere Versionen gefunden.


Ps: Ich poste diese Antwort hier, da mich die Frage hierher geführt hat, obwohl das OP nach einer Antwort auf eine andere Frage gesucht hat.

Florian Breisch
quelle
2
Dies scheint bei weitem der zuverlässigste Ansatz zu sein, danke. Funktioniert jedoch nur für Version> = 3.0.0.
Filip
@daluege - danke für die Inspiration. Ich habe leider keinen Beweis für weniger als 0,10 gefunden.
Florian Breisch
3
Ich habe festgestellt, dass ich das React Webpack verwende processund process.versiones im Bundle vorhanden ist. Daher habe ich eine zusätzliche Überprüfung hinzugefügt, process.versionwo process.release.nodeauf der Clientseite undefiniert ist, auf der Serverseite jedoch eine Knotenversion als Wert
Aaron
@ Aaron: Danke für diesen Hinweis. Ich konnte keine Definition der process.versionVariablen finden (in React, Webpack oder React-Webpack). Ich würde mich über jeden Hinweis freuen, in dem die Versionsvariable definiert ist, um sie der Antwort hinzuzufügen. Abhängig von release.node Einschränkungen für Knoten> = 3.xx
Florian Breisch
2
function isNodejs() { return typeof "process" !== "undefined" && process && process.versions && process.versions.node; }
Einzeiler
25

Das Problem beim Versuch herauszufinden, in welcher Umgebung Ihr Code ausgeführt wird, besteht darin, dass jedes Objekt geändert und deklariert werden kann, sodass es nahezu unmöglich ist, herauszufinden, welche Objekte in der Umgebung nativ sind und welche vom Programm geändert wurden.

Es gibt jedoch einige Tricks, mit denen wir herausfinden können, in welcher Umgebung Sie sich befinden.

Beginnen wir mit der allgemein akzeptierten Lösung, die in der Unterstrichbibliothek verwendet wird:

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

Diese Technik ist für die Serverseite eigentlich vollkommen in Ordnung, da beim requireAufrufen der Funktion das thisObjekt auf ein leeres Objekt zurückgesetzt und modulefür Sie neu definiert wird, sodass Sie sich keine Gedanken über Manipulationen von außen machen müssen. Solange Ihr Code mit geladen ist require, sind Sie sicher.

Dies fällt jedoch im Browser auseinander, da jeder leicht definieren kann module, dass es so aussieht, als wäre es das Objekt, nach dem Sie suchen. Dies kann einerseits das gewünschte Verhalten sein, bestimmt aber auch, welche Variablen der Bibliotheksbenutzer im globalen Bereich verwenden kann. Vielleicht hat jemand will eine Variable mit dem Namen verwenden module, der hat exportsin der es für eine andere Verwendung. Es ist unwahrscheinlich, aber wer sollen wir beurteilen, welche Variablen jemand anderes verwenden kann, nur weil eine andere Umgebung diesen Variablennamen verwendet?

Der Trick ist jedoch, dass, wenn wir davon ausgehen, dass Ihr Skript im globalen Bereich geladen wird (was auch der Fall ist, wenn es über ein Skript-Tag geladen wird), eine Variable nicht in einem äußeren Abschluss reserviert werden kann, da der Browser dies nicht zulässt . Denken Sie nun daran, dass das thisObjekt im Knoten ein leeres Objekt ist und die moduleVariable dennoch verfügbar ist. Das liegt daran, dass es in einem äußeren Verschluss deklariert ist. So können wir den Check des Unterstrichs korrigieren, indem wir einen zusätzlichen Check hinzufügen:

this.module !== module

Wenn jemand moduleim Browser den globalen Bereich deklariert , wird er im thisObjekt platziert, wodurch der Test fehlschlägt, da er this.moduledasselbe Objekt wie das Modul ist. Auf dem Knoten ist this.modulenicht vorhanden und modulebefindet sich innerhalb eines äußeren Verschlusses, sodass der Test erfolgreich ist, da sie nicht gleichwertig sind.

Somit ist der letzte Test:

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

Hinweis: Auf diese Weise kann die moduleVariable jetzt im globalen Bereich frei verwendet werden. Sie können dies jedoch im Browser umgehen, indem Sie einen neuen Abschluss erstellen und diesen deklarieren moduleund dann das Skript in diesen Abschluss laden. Zu diesem Zeitpunkt repliziert der Benutzer die Knotenumgebung vollständig und weiß hoffentlich, was er tut, und versucht, einen erforderlichen Knotenstil auszuführen. Wenn der Code in einem Skript-Tag aufgerufen wird, ist er weiterhin vor neuen äußeren Verschlüssen geschützt.

Zeit
quelle
2
Wow, danke, dass du die Gründe für jedes Stück deines Einzeilers klar erklärt hast.
Jon Coombs
bekam, Cannot read property 'module' of undefinedweil dies zum Beispiel in Mokka-Tests undefiniert ist
srghma
20

Folgendes funktioniert im Browser, sofern nicht absichtlich explizit sabotiert:

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

Bam.

user3751385
quelle
4
var process = {toString: function () {return '[Objektprozess]'; }};
Nick Desaulniers
1
Gibt es einen Grund, warum Sie process+''anstelle von verwenden process.toString()?
Harmic
3
Fast. Verwenden Sie dies stattdessen:Object.prototype.toString.call(process)
Sospedra
2
Dies ist die beste Antwort auf diese Frage.
Loretoparisi
3
@harmic: var process = null;würde dazu führen, dass der zweite Fall fehlschlägt. Sowohl in Javascript als auch in Java '' + xerzeugt der Ausdruck dasselbe, x.toString()außer wenn er xböse ist, der erstere erzeugt "null"oder "undefined"wo der letztere einen Fehler auslösen würde.
Joeytwiddle
17

Hier ist eine ziemlich coole Möglichkeit, dies ebenfalls zu tun:

const isBrowser = this.window === this;

Dies funktioniert, weil in Browsern die globale Variable 'this' eine Selbstreferenz namens 'window' hat. Diese Selbstreferenz ist in Node nicht vorhanden.

  • Im Browser ist 'this' ein Verweis auf das globale Objekt 'window'.
  • Im Knoten ist 'this' ein Verweis auf das Objekt module.exports.
    • 'this' ist kein Verweis auf das Node Global Object, das als 'global' bezeichnet wird.
    • 'this' ist kein Verweis auf den Deklarationsraum der Modulvariablen.

Um die oben vorgeschlagene Browserüberprüfung zu unterbrechen, müssten Sie Folgendes tun

this.window = this;

vor dem Ausführen der Prüfung.

Patrick
quelle
Warum nicht einfach const isBrowser = this.window !== undefined? Und theoretisch kann ich im Knoten this.window = thisdie Lösung täuschen.
Tyler Long
11

Noch eine Umgebungserkennung :

(Das heißt: Die meisten Antworten hier sind in Ordnung.)

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 ?..
}

Ein bisschen paranoid, oder? Sie können dies ausführlicher gestalten, indem Sie nach mehr Globalen suchen .

Aber NICHT!.

All dies kann sowieso gefälscht / simuliert werden.

Zum Beispiel, um das globalObjekt zu fälschen :

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

Dies wird nicht an das ursprüngliche globale Objekt des Knotens angehängt, sondern an das windowObjekt in einem Browser. Es bedeutet also, dass Sie sich in Node env in einem Browser befinden.

Das Leben ist kurz!

Interessiert es uns, wenn unsere Umwelt gefälscht ist? Es würde passieren, wenn ein dummer Entwickler eine globale Variable deklariert, die globalim globalen Bereich aufgerufen wird . Oder ein böser Entwickler fügt irgendwie Code in unsere Umgebung ein.

Wir können verhindern, dass unser Code ausgeführt wird, wenn wir dies abfangen, aber viele andere Abhängigkeiten unserer App können davon betroffen sein. Also wird der Code irgendwann kaputt gehen. Wenn Ihr Code gut genug ist, sollten Sie sich nicht um jeden dummen Fehler kümmern, den andere hätten machen können.

Na und?

Wenn Sie auf zwei Umgebungen abzielen: Browser und Knoten;
"use strict";; und entweder einfach nach windowoder suchen global; und geben Sie in den Dokumenten deutlich an, dass Ihr Code nur diese Umgebungen unterstützt. Das ist es!

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

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

Wenn möglich für Ihren Anwendungsfall; anstelle der Umgebungserkennung; Führen Sie eine synchrone Feature-Erkennung innerhalb eines Try / Catch-Blocks durch. (Die Ausführung dauert einige Millisekunden).

z.B

function isPromiseSupported() {
    var supported = false;
    try {
        var p = new Promise(function (res, rej) {});
        supported = true;
    } catch (e) {}
    return supported;
}
Onur Yıldırım
quelle
9

Die meisten der vorgeschlagenen Lösungen können tatsächlich gefälscht werden. Eine robuste Methode besteht darin, die interne ClassEigenschaft des globalen Objekts mithilfe von zu überprüfen Object.prototype.toString. Die interne Klasse kann in JavaScript nicht gefälscht werden:

var isNode = 
    typeof global !== "undefined" && 
    {}.toString.call(global) == '[object global]';
Fabian Jakobs
quelle
2
Dies wird unter browserify wieder zutreffen.
Alt
1
Hast du das getestet? Ich kann nicht sehen, wie browserify die interne Klasse eines Objekts ändern kann. Dies würde das Ändern des Codes in der JavaScript-VM oder das Überschreiben erfordern, Object.prototype.toStringwas wirklich eine schlechte Praxis ist.
Fabian Jakobs
Ich habe es getestet. Hier ist, was browserify macht:var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
Vanuan
Sie sehen, in Chrome ({}.toString.call(window))ist gleich "[object global]".
Vanuan
2
Es ist seltsam, weil window.toString()produziert"[object Window]"
Vanuan
5

Was ist das Prozessobjekt und Überprüfung mit execPath für node?

process.execPath

Dies ist der absolute Pfadname der ausführbaren Datei, die den Prozess gestartet hat.

Beispiel:

/ usr / local / bin / node

Kevin Hakanson
quelle
2
Was ist mit window.process = {execPath: "/usr/local/bin/node"};?
23онстантин Ван
4

Hier ist meine Variation von dem, was oben steht:

(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;});

Um es zu verwenden, ändern Sie das "Haus" in der vorletzten Zeile so, dass der Name des Moduls im Browser angezeigt wird, und veröffentlichen den gewünschten Wert des Moduls (normalerweise ein Konstruktor oder ein Objektliteral) ).

In Browsern ist das globale Objekt window und hat einen Verweis auf sich selbst (es gibt ein window.window, das == window ist). Es scheint mir, dass dies unwahrscheinlich ist, wenn Sie sich nicht in einem Browser oder in einer Umgebung befinden, in der Sie glauben sollen, dass Sie sich in einem Browser befinden. In allen anderen Fällen, wenn eine globale 'Modul'-Variable deklariert ist, wird diese verwendet, andernfalls wird das globale Objekt verwendet.

kybernetikos
quelle
4

Ich verwende process, um nach node.js zu suchen

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

oder

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

dokumentierte hier

Chris
quelle
2
process.titlekann geändert werden
Ben Barkay
Suchen Sie dann nach dem Titel, in den Sie ihn geändert haben. Oder verwenden Sie process.version
Chris
Wenn Sie für eine Bibliothek schreiben (wie Sie sollten), können Sie nicht erwarten, wie der Titel lauten sollte
Ben Barkay
3

Zum jetzigen Zeitpunkt handelt es sich bei dieser Antwort eher um eine "Coming Soon" -Option, da sie sehr neue Funktionen von JavaScript nutzt.

const runtime = globalThis.process?.release?.name || 'not node'
console.log(runtime)

Der runtimeWert ist entweder nodeoder not node.

Wie bereits erwähnt, basiert dies auf einigen neuen JavaScript-Funktionen. globalThisist eine endgültige Funktion in der ECMAScript 2020-Spezifikation. In der V8-Engine, die im Lieferumfang von Chrome 80 enthalten ist, wird optionales Verketten / Null-Zusammenführen (der ?Teil von globalThis.process?.release?.name) unterstützt. Ab dem 08.04.2020 funktioniert dieser Code im Browser, jedoch nicht in Node, da der Node 13-Zweig verwendet V8 7.9.xxx. Ich glaube, dass Node 14 (voraussichtlich am 21.04.2020 veröffentlicht) V8 8.x + verwenden soll.

Dieser Ansatz bringt eine gesunde Dosis aktueller Einschränkungen mit sich. Jedoch; Das Tempo, mit dem Browser / Knoten veröffentlicht werden, wird letztendlich ein zuverlässiger Einzeiler sein.

Corey
quelle
1
Dies sollte die akzeptierte Antwort sein! und jeder sollte übrigens Knoten 14 benutzen
Sceat
2

Node.js hat ein processObjekt. Solange Sie kein anderes Skript haben, das erstellt wird, processkönnen Sie damit bestimmen, ob Code auf Node ausgeführt wird.

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
quelle
2

Dies ist eine ziemlich sichere und unkomplizierte Methode, um die Kompatibilität zwischen serverseitigem und clientseitigem Javascript sicherzustellen, das auch mit browserify, RequireJS oder CommonJS einschließlich clientseitig funktioniert:

(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;
}())
Christophe Marois
quelle
1

Bearbeiten : Zu Ihrer aktualisierten Frage: "Wie kann ein Skript feststellen, ob es als CommonJS-Modul erforderlich war?" Ich glaube nicht, dass es geht. Sie können überprüfen, ob exportses sich um ein Objekt ( if (typeof exports === "object")) handelt, da die Spezifikation die Bereitstellung für Module erfordert. Sie müssen jedoch nur angeben, dass ... exportsein Objekt ist. :-)


Ursprüngliche Antwort:

Ich bin mir sicher, dass es ein NodeJS-spezifisches Symbol gibt ( EventEmittervielleicht nein, Sie müssen es verwenden require, um das Ereignismodul abzurufen; siehe unten ), nach dem Sie suchen könnten, aber wie David sagte, ist es im Idealfall besser, die Funktion zu erkennen (eher als Umwelt), wenn es Sinn macht, dies zu tun.

Update : Vielleicht so etwas wie:

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

Aber das sagt dir nur, dass du in einer Umgebung mit requireund etwas sehr, sehr ähnlichem wie NodeJS bist Buffer. :-)

TJ Crowder
quelle
Ich kann das immer noch brechen, indem ich all das Zeug auf einer Website einrichte ... das ist einfach übertrieben;) Das Überprüfen, ob ich mich in einem Browser befinde, ist einfacher, da die Node-Umgebung sauberer ist.
Ivo Wetzel
1
@Ivo: Ja, siehe meinen letzten Satz. Ich kann Ihre Prüfung genauso einfach windowaufheben , indem ich eine Variable in einer NodeJS-Anwendung definiere. :-)
TJ Crowder
1
@ Ivo: Ich würde nicht sein alle überrascht , wenn jemand definiert windowin einem NodeJS Modul, so dass sie Code enthalten könnten , die Verlass windowist das globale Objekt und nicht , dass Code ändern möchten. Ich würde es nicht tun, du würdest es nicht tun , aber ich wette, jemand hat es getan . :-) Oder sie haben einfach windowetwas ganz anderes gemeint.
TJ Crowder
1
@Ivo: yuiblog.com/blog/2010/04/09/… ist ein Grund, warum das Fensterobjekt in node.js definiert werden kann
slebetman
1
@TJCrowdertypeof process !== "undefined" && process.title === "node"
Raynos
0
const isNode =
  typeof process !== 'undefined' &&
  process.versions != null &&
  process.versions.node != null;
BAR
quelle
-1

Nehmen Sie die Quelle von node.js und ändern Sie sie, um eine Variable wie zu definieren runningOnNodeJS. Suchen Sie in Ihrem Code nach dieser Variablen.

Wenn Sie keine eigene private Version von node.js haben können, öffnen Sie eine Funktionsanforderung im Projekt. Bitten Sie sie, eine Variable zu definieren, die Ihnen die Version von node.js gibt, in der Sie ausgeführt werden. Überprüfen Sie dann, ob diese Variable vorhanden ist.

Aaron Digulla
quelle
1
Das löst sein (im Grunde unlösbares) Problem wieder nicht, ich kann wieder einfach eine solche Variable im Browser erstellen. Besser wäre es, zu verhindern, dass Skripte ein windowglobales erstellen. Ich schätze, ich werde eine Feature-Anfrage für dieses Skript einreichen.
Ivo Wetzel
@Ivo: Das ist eine schlechte Idee, die Code brechen würde, der jsdom ( github.com/tmpvar/jsdom ) verwendet, um serverseitige Dom-Manipulationen mit vertrauten Bibliotheken wie YUI und jQuery durchzuführen . Und es gibt derzeit Code in der Produktion, der dies tut.
Slebetman
@slebetman Nein, es wird jsdom nicht brechen. Ich spreche von global , wie in keiner var-Anweisung global , der dortige Beispielcode verwendet die varAnweisung, Leute, die sie nur in den globalen Namespace lecken, und sie bekommen dann nicht das Konzept von in sich geschlossenen Modulen
Ivo Wetzel
@Ivo das ist irgendwie gewalttätig, es ist wie zu sagen, wir sollten die Fähigkeit nutzen, Kuchen zu essen, weil die Leute fett werden, wenn sie sie zu viel essen. Sie müssen den globalen Namespace überladen, um eine Bibliothek zu erhalten, die zwischen den Modulen funktioniert. Oder Sie könnten alles in einem einzigen Modul zusammenfassen, aber worum geht es dann?
Ben Barkay
-1

Sehr alter Beitrag, aber ich habe ihn gerade gelöst, indem ich die erforderlichen Anweisungen in einen Try-Catch eingewickelt habe

try {
     var fs = require('fs')
} catch(e) {
     alert('you are not in node !!!')
}
Stef de Vries
quelle
2
Das ist nicht wahr, Sie können browserify verwenden, um "nodeish" require () -Aufrufe zu verwenden
fat