Comment vérifier si un script s'exécute sous node.js?
J'ai un script que j'exige d'un nœud.script js, que je veux garder indépendant du moteur javascript.
Donc, par exemple, je veux faire:
exports.x = y;
Seulement s'il s'exécute sous node.js. comment puis-je effectuer ce test?
Edit: Lors de la publication de cette question, je ne connaissais pas le nœud.la fonctionnalité des modules js est basée sur commonjs .
Pour l'exemple spécifique, j'ai donné une question plus précise aurait été:
Comment un script peut-il dire si a été nécessaire en tant que module commonjs?
17 réponses
Voici comment le trait de soulignement .JS la bibliothèque le fait (en recherchant le support CommonJS):
Modifier: à votre question mise à jour:
(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._ = _;
}
})();
Exemple ici conserve le modèle de Module.
Eh bien, il n'y a pas de moyen fiable de détecter l'exécution dans le nœud.js puisque chaque site Web pourrait facilement déclarer les mêmes variables, pourtant, puisqu'il n'y a pas d'objet window
dans le nœud.js par défaut, vous pouvez aller dans l'autre sens et vérifier si vous exécutez dans un navigateur.
C'est ce que j'utilise pour les bibliothèques qui devraient fonctionner à la fois dans un navigateur et sous Node.js:
if (typeof window === 'undefined') {
exports.foo = {};
} else {
window.foo = {};
}
Il pourrait encore exploser dans le cas où window
est défini dans le nœud.js mais il n'y a pas de bonne raison pour quelqu'un faites ceci, puisque vous devez explicitement laisser var
ou définir la propriété sur l'objet global
.
Modifier
Pour détecter si votre script a été requis en tant que module CommonJS, ce n'est pas facile. La seule chose que commonJS spécifie est que A: les modules seront inclus via un appel à la fonction require
et B: les modules exportent des choses via des propriétés sur l'objet exports
. Maintenant, comment cela est mis en œuvre est laissé au système sous-jacent. Nœud.js enveloppe le contenu des modules dans un funciton anonyme.
function (exports, require, module, __filename, __dirname) {
Voir: https://github.com/ry/node/blob/master/src/node.js#L325
Mais n'y allez pas en essayant de détecter cela via des trucsarguments.callee.toString()
fous, utilisez plutôt mon exemple de code ci-dessus qui vérifie le navigateur, Node.js est un environnement plus propre, il est donc peu probable que window
y soit déclaré.
Le problème avec essayer de comprendre dans quel environnement votre code s'exécute est que n'importe quel objet peut être modifié et déclaré, ce qui rend presque impossible de déterminer quels objets sont natifs de l'environnement et lesquels ont été modifiés par le programme.
Cependant, il y a quelques astuces que nous pouvons utiliser pour déterminer avec certitude dans quel environnement vous vous trouvez.
Commençons par la solution généralement acceptée utilisée dans le trait de soulignement bibliothèque:
typeof module !== 'undefined' && module.exports
Cette technique est en fait parfaitement adaptée au côté serveur, car lorsque la fonction require
est appelée, elle réinitialise l'objet this
sur un objet vide et redéfinit module
pour vous, ce qui signifie que vous n'avez pas à vous soucier de toute altération extérieure. Tant que votre code est chargé avec require
, vous êtes en sécurité.
Cependant, cela tombe en morceaux sur le navigateur, car n'importe qui peut facilement définir module
pour donner l'impression que c'est l'objet que vous recherchez. Sur un hand cela peut être le comportement que vous voulez, mais il dicte également les variables que l'utilisateur de la bibliothèque peut utiliser dans la portée globale. Peut-être que quelqu'un veut utiliser une variable avec le nom module
qui a exports
à l'intérieur pour un autre usage. C'est peu probable, mais qui sommes-nous pour juger quelles variables quelqu'un d'autre peut utiliser, juste parce qu'un autre environnement utilise ce nom de variable?
L'astuce cependant, est que si nous supposons que votre script est chargé dans la portée globale (ce qui sera le cas si c'est une variable ne peut pas être réservée dans une fermeture externe, car le navigateur ne le permet pas. Rappelez-vous maintenant dans node, l'objet this
est un objet vide, mais la variable module
est toujours disponible. C'est parce qu'il est déclaré dans une fermeture externe. Nous pouvons donc corriger la vérification de underscore en ajoutant une vérification supplémentaire:
this.module !== module
, Avec cela, si quelqu'un déclare module
dans la portée globale dans le navigateur, il sera placé dans le this
objet, ce qui va provoquer le test échoue, car this.module
, sera le même objet que le module. Sur le nœud, this.module
n'existe pas, et module
existe dans une fermeture externe, de sorte que le test réussira, car ils ne sont pas équivalents.
Ainsi, le test final est:
typeof module !== 'undefined' && this.module !== module
Note: Bien que cela permette maintenant à la variable module
d'être utilisée librement dans la portée globale, il est toujours possible de contourner cela sur le navigateur en créant une nouvelle fermeture et en déclarant module
à l'intérieur, puis en chargeant le script dans que cette fermeture. À ce stade, l'utilisateur réplique entièrement l'environnement de nœud et, espérons-le, sait ce qu'il fait et essaie de faire un style de nœud requis. Si le code est appelé dans une balise de script, il sera toujours à l'abri de toute nouvelle fermeture externe.
Je suis actuellement tombé sur une mauvaise détection de noeud qui n'est pas au courant de L'environnement de noeud dans Electron en raison d'une détection de caractéristique trompeuse. Les solutions suivantes identifient explicitement l'environnement de processus.
Identifier Le Nœud.js seulement
(typeof process !== 'undefined') && (process.release.name === 'node')
Cela va découvrir si vous exécutez dans un processus de Noeud, puisque process.release
contient les "métadonnées relatives à la version [Node-]actuelle".
Après le spawn de io.js la valeur de process.release.name
peut également devenir io.js
(voir la processus-doc). Pour détecter correctement un environnement prêt au nœud, je suppose que vous devriez vérifier comme suit:
Identifier le nœud (>=3.0.0) ou io.js
(typeof process !== 'undefined') &&
(process.release.name.search(/node|io.js/) !== -1)
Cette instruction a été testée avec le noeud 5.5.0, Electron 0.36.9 (avec le noeud 5.1.1) et Chrome 48.0.2564.116.
Identifier le noeud (>=0.10.0) ou io.js
(typeof process !== 'undefined') &&
(typeof process.versions.node !== 'undefined')
Le commentaire de@daluege m'a inspiré à penser à une preuve plus générale. Cela devrait fonctionner à partir du nœud.js >= 0.10. Je n'ai pas trouvé d'identifiant unique pour les versions antérieures.
p. s.: je poste cette réponse ici puisque la question me mène ici, bien que le PO cherchait une réponse à une question différente.
Ce qui suit fonctionne dans le navigateur sauf si intentionnellement, explicitement saboté:
if(typeof process === 'object' && process + '' === '[object process]'){
// is node
}
else{
// not node
}
Bam.
La Plupart des solutions proposées peuvent effectivement être faux. Un moyen robuste consiste à vérifier la propriété interne Class
de l'objet global en utilisant Object.prototype.toString
. La classe interne ne peut pas être truquée en JavaScript:
var isNode =
typeof global !== "undefined" &&
{}.toString.call(global) == '[object global]';
Voici une façon assez cool de le faire aussi:
const isBrowser = this.window === this;
Cela fonctionne car dans les navigateurs, la variable globale 'this' a une auto-référence appelée 'window'. Cette auto-référence n'existe pas dans le nœud.
- Dans le navigateur 'ce' est une référence à l'objet global, appelé "fenêtre".
- dans le noeud 'this' est une référence au module.exportation
objet.
- 'ceci' est Pas une référence à L'objet global de Noeud, appelé 'global'.
- 'ceci' est Pas {[13] } une référence à l'espace de déclaration de variable du module.
Pour casser la vérification du navigateur suggérée ci-dessus, vous devez faire quelque chose comme
this.window = this;
Avant d'exécuter la vérification.
Encore un autre détection de l'environnement :
(Signification: la plupart des réponses ici sont correctes.)
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 ?..
}
Un peu paranoïaque Non? Vous pouvez rendre cela plus verbeux en vérifiant plus de globals .
, Mais NE le faites PAS!.
Tout ce qui précède peut être truqué/simulé de toute façon.
Par exemple pour simuler l'objet global
:
global = {
toString: function () {
return '[object global]';
},
GLOBAL: global,
setImmediate: function (a, b, c, d) {}
};
setImmediate = function (a, b, c, d) {};
...
Cela ne sera pas attaché à l'objet global d'Origine du nœud mais il sera attaché au window
objet dans un navigateur. Cela impliquera donc que vous êtes dans Node env dans un navigateur.
La Vie est courte!
- on si notre environnement est truquée? Cela se produirait quand un développeur stupide déclarerait une variable globale appelée global
dans la portée globale. Ou un dev maléfique injecte du code dans notre env en quelque sorte.
, Nous pouvons empêcher notre code de s'exécuter lorsque nous attraper cette mais beaucoup d'autres dépendances de notre application peut se coincer dans cette. Donc, finalement, le code va se casser. Si votre le code est assez bon, vous ne devriez pas vous soucier de chaque erreur stupide qui aurait pu être faite par d'autres.
Et Alors?
Si vous ciblez 2 environnements: navigateur et noeud;"use strict"
; et vérifiez simplement window
ou global
; et indiquez clairement que dans les documents, votre code ne prend en charge que ces environnements. Ça y est!
var isBrowser = typeof window !== 'undefined'
&& ({}).toString.call(window) === '[object Window]';
var isNode = typeof global !== "undefined"
&& ({}).toString.call(global) === '[object global]';
Si possible pour votre cas d'utilisation; au lieu de la détection de l'environnement; faites la détection de fonctionnalité synchrone dans un bloc try/catch. (ils prend quelques millisecondes à exécuter).
Par exemple
function isPromiseSupported() {
var supported = false;
try {
var p = new Promise(function (res, rej) {});
supported = true;
} catch (e) {}
return supported;
}
Qu'en est-il de l'utilisation de l'objet process et de la vérification de execPath pour node
?
Processus.execPath
C'est l'absolu chemin d'accès du fichier exécutable de commencer le processus.
Exemple:
/usr/local/bin/node
Comment un script peut-il indiquer s'il a été requis en tant que module commonjs?
Connexes: pour vérifier s'il a été nécessaire en tant que module vs exécuter directement dans le nœud, vous pouvez vérifier require.main !== module
.
http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module
Voici ma variation sur ce qui est ci-dessus:
(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;});
Pour l'utiliser, vous devez modifier la "Maison" sur la deuxième ligne à être ce que vous voulez le nom du module dans le navigateur et de publier ce que vous voulez de la valeur du module (généralement un constructeur ou un objet littéral).
Dans les navigateurs, l'objet global est window, et il a une référence à lui-même (il y a une fenêtre.fenêtre = fenêtre). Il me semble que cela est peu susceptible de se produire sauf si vous êtes dans un navigateur ou dans un environnement qui veut vous faire croire que vous êtes dans un navigateur. Dans tous les autres cas, s'il y a une variable 'module' globale déclarée, elle l'utilise sinon elle utilise l'objet global.
J'utilise process
pour vérifier le nœud.js comme ça
if (typeof(process) !== 'undefined' && process.version === 'v0.9.9') {
console.log('You are running Node.js');
} else {
// check for browser
}
Ou
if (typeof(process) !== 'undefined' && process.title === 'node') {
console.log('You are running Node.js');
} else {
// check for browser
}
Documenté ici
Noeud.js a un objet process
, donc tant que vous n'avez aucun autre script qui crée process
, Vous pouvez l'utiliser pour déterminer si le code s'exécute sur le nœud.
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");
}
C'est un moyen assez sûr et simple d'assurer la compatibilité entre javascript côté serveur et côté client, qui fonctionnera également avec browserify, RequireJS ou CommonJS inclus côté client:
(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;
}())
Edit : en ce qui concerne votre question mise à jour: " Comment un script peut-il dire s'il a été requis en tant que module commonjs?" Je ne pense pas que ce soit possible. Vous pouvez vérifier si exports
est un objet (if (typeof exports === "object")
), puisque la spécification nécessite qu'elle soit fournie aux modules, mais tout ce qui vous dit est cela ... exports
est un objet. :-)
Réponse originale:
Je suis sûr qu'il y a un symbole spécifique à NodeJS( non, vous devez utiliser EventEmitter
, peut êtrerequire
pour obtenez le module events; voir ci-dessous) que vous pourriez vérifier, mais comme David l'a dit, idéalement, vous feriez mieux de détecter la fonctionnalité (plutôt que l'environnement) si cela a du sens.
Mise à Jour: peut-être quelque chose comme:
if (typeof require === "function"
&& typeof Buffer === "function"
&& typeof Buffer.byteLength === "function"
&& typeof Buffer.prototype !== "undefined"
&& typeof Buffer.prototype.write === "function") {
Mais cela vous indique simplement que vous êtes dans un environnement avec require
et quelque chose de très, très semblable à celui de NodeJS Buffer
. :-)
Prenez la source du nœud.js et modifiez-le pour définir une variable comme runningOnNodeJS
. Vérifiez cette variable dans votre code.
Si vous ne pouvez pas avoir votre propre version de nœud.js, ouvrez une demande de fonctionnalité dans le projet. Demandez qu'ils définissent une variable qui vous donne la version de node.js que vous courez dans. Ensuite, vérifiez cette variable.
Très ancien post, mais je viens de le résoudre en enveloppant les instructions require dans un try-catch
try {
var fs = require('fs')
} catch(e) {
alert('you are not in node !!!')
}