Jak sprawdzić, czy skrypt jest uruchomiony pod węzłem.js?

Mam skrypt, którego wymagam od węzła.skrypt js, który chcę zachować niezależny silnik javascript.

Więc, na przykład, chcę zrobić:

exports.x = y;

Tylko wtedy, gdy działa pod węzłem.js. Jak mogę wykonać ten test?

Edit: wrzucając to pytanie, nie znałem węzła.Funkcja Modułów js opiera się na commonjs.

Dla konkretnego przykładu podałem dokładniejsze pytanie brzmiałoby:

Jak skrypt może stwierdzić, czy to czy był wymagany jako wspólny moduł js?

Author: theosp, 2010-11-19

17 answers

Tak podkreślają .biblioteka js robi to (szukając wsparcia CommonJS):

Edit: do twojego zaktualizowanego pytania:

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

Przykład tutaj zachowuje wzór modułu.

 73
Author: Ross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 16:19:28

Cóż, nie ma niezawodnego sposobu na wykrycie działania w węźle.js, ponieważ każda strona internetowa może łatwo zadeklarować te same zmienne, jednak, ponieważ nie ma window obiektu w węźle.js domyślnie możesz przejść na drugą stronę i sprawdzić, czy działasz w przeglądarce.

To jest to, czego używam do bibliotek, które powinny działać zarówno w przeglądarce, jak i pod węzłem.js:

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

} else {
    window.foo = {};
}

Może nadal eksplodować w przypadku, gdy window jest zdefiniowany w Node.js ale nie ma dobrego powodu dla kogoś zrób to, ponieważ musisz wyraźnie pominąć var lub ustawić właściwość na obiekcie global.

EDIT

Aby wykryć, czy twój skrypt jest wymagany jako moduł CommonJS, to znowu nie jest łatwe. CommonJS określa tylko to, że a: moduły będą dołączane poprzez wywołanie funkcji require i B: Moduły eksportują rzeczy poprzez właściwości obiektu exports. Teraz jak to jest zaimplementować pozostaje do systemu bazowego. Węzeł.js owija zawartość modułów w funkcji anonimowej.

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

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

Ale nie idź tam, próbując wykryć to za pomocą jakichś szalonych rzeczy arguments.callee.toString(), zamiast tego użyj mojego przykładowego kodu powyżej, który sprawdza przeglądarkę, węzeł.js jest sposobem na czystsze środowisko, więc jest mało prawdopodobne, że window zostanie tam zadeklarowana.

 72
Author: Ivo Wetzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-19 12:21:47

Problem z próbowaniem dowiedzieć się, w jakim środowisku działa kod polega na tym, że każdy obiekt może być modyfikowany i deklarowany, co sprawia, że prawie niemożliwe jest ustalenie, które obiekty są rodzime dla środowiska, a które zostały zmodyfikowane przez program.

Jest jednak kilka sztuczek, których możemy użyć, aby dowiedzieć się, w jakim środowisku się znajdujesz.

Zacznijmy od ogólnie przyjętego rozwiązania, które jest używane w podkreślniku biblioteka:

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

Ta technika jest właściwie w porządku dla strony serwera, ponieważ gdy wywołana jest funkcja require, resetuje this obiekt do pustego obiektu i ponownie definiuje module dla ciebie, co oznacza, że nie musisz się martwić o jakiekolwiek zewnętrzne manipulacje. Dopóki twój kod jest załadowany require, jesteś bezpieczny.

Jednak to się rozpada w przeglądarce, ponieważ każdy może łatwo zdefiniować module, aby wyglądało na to, że jest to obiekt, którego szukasz. On one ręka to może być zachowanie, które chcesz, ale również dyktuje, jakie zmienne użytkownik biblioteki może używać w zakresie globalnym. Może ktoś chce użyć zmiennej o nazwie module, która ma exports w środku do innego zastosowania. To mało prawdopodobne, ale kim jesteśmy, aby oceniać, jakich zmiennych może używać ktoś inny, tylko dlatego, że inne środowisko używa tej nazwy zmiennej?

Sztuczka polega jednak na tym, że jeśli Zakładamy, że Twój skrypt jest ładowany w zasięgu globalnym (co będzie, jeśli loaded via script tag) zmienna nie może być zarezerwowana w zewnętrznym zamknięciu, ponieważ przeglądarka na to nie pozwala. Pamiętaj, że w node obiekt {[2] } jest pustym obiektem, ale zmienna module jest nadal dostępna. To dlatego, że jest zadeklarowana w zewnętrznym zamknięciu. Tak więc możemy naprawić sprawdzanie podkreślenia przez dodanie dodatkowego sprawdzania:

this.module !== module

Z tym, jeśli ktoś zadeklaruje module w zasięgu globalnym w przeglądarce, zostanie on umieszczony w obiekcie this, co spowoduje test, który się nie powiedzie, ponieważ this.module, będzie tym samym obiektem co moduł. Na węźle this.module nie istnieje, a module istnieje w zewnętrznym zamknięciu, więc test się powiedzie, ponieważ nie są równoważne.

Zatem ostateczny test to:

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

Uwaga: chociaż pozwala to na swobodne użycie zmiennej module w zasięgu globalnym, nadal można to ominąć w przeglądarce, tworząc nowe zamknięcie i deklarując module w nim, a następnie ładując skrypt w nim to zamknięcie. W tym momencie użytkownik jest w pełni replikacji środowiska węzła i mam nadzieję, że wie, co robią i próbuje zrobić styl węzeł wymagają. Jeśli kod zostanie wywołany w znaczniku script, nadal będzie bezpieczny przed nowymi zewnętrznymi zamknięciami.

 24
Author: TimE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-11 23:06:41

Obecnie natknąłem się na błędne wykrywanie węzła, który jest nie świadomy środowiska węzła wElektron ze względu na mylące wykrywanie cech. Poniższe rozwiązania jednoznacznie identyfikują środowisko procesowe.


Zidentyfikuj Węzeł.tylko js

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

To odkryje, czy działasz w procesie węzłowym, ponieważ process.release zawiera "metadane związane z bieżącym wydaniem [Node -]".

Po odradzaniu się io.js wartość process.release.name może również stać się io.js (Zobacz proces-Doc). Aby poprawnie wykryć środowisko gotowe do węzła, powinieneś sprawdzić w następujący sposób:

Identify Node (>=3.0.0) or io.js

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

To stwierdzenie zostało przetestowane z Node 5.5.0, Electron 0.36.9 (z Node 5.1.1) i Chrome 48.0.2564.116.

Zidentyfikuj węzeł (>=0.10.0) lub io.js

(typeof process !== 'undefined') &&
(typeof process.versions.node !== 'undefined')
Komentarz @ daluege zainspirował mnie do zastanowienia się nad bardziej ogólnym dowodem. Powinno to działać z węzła.js >= 0.10. Nie znalazłem unikalnego identyfikatora dla poprzednich wersji.

P. s.: zamieszczam tutaj tę odpowiedź, ponieważ pytanie mnie tu prowadzi, chociaż OP szukał odpowiedzi na inne pytanie.

 21
Author: florianb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-28 14:07:55

Poniższe działa w przeglądarce, chyba że celowo, wyraźnie sabotażowane:

if(typeof process === 'object' && process + '' === '[object process]'){
    // is node
}
else{
    // not node
}
Bam.
 20
Author: user3751385,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-30 00:09:39

Większość proponowanych rozwiązań może być faktycznie sfałszowana. Solidnym sposobem jest sprawdzenie wewnętrznej właściwości Class obiektu globalnego za pomocą Object.prototype.toString. Klasa wewnętrzna nie może być sfałszowana w JavaScript:

var isNode = 
    typeof global !== "undefined" && 
    {}.toString.call(global) == '[object global]';
 9
Author: Fabian Jakobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-05 11:53:42

Tutaj jest całkiem fajny sposób, aby to zrobić, jak również:

const isBrowser = this.window === this;

To działa, ponieważ w przeglądarkach globalna zmienna 'this' ma odniesienie do siebie o nazwie 'window'. To samo odniesienie nie istnieje w Node.

  • w przeglądarce 'this' jest odniesieniem do globalnego obiektu o nazwie 'window'.
  • W Node 'this' jest odniesienie do modułu.wywóz obiekt.
    • 'this' is not a reference to the node global object, called 'global'.
    • ' to ' jest Nie odniesienie do przestrzeni deklaracji zmiennej modułu.

Aby złamać powyższe sugerowane sprawdzenie przeglądarki, musisz zrobić coś takiego jak poniżej

this.window = this;

Przed wykonaniem kontroli.

 9
Author: Patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-25 23:21:01

Yet another Detekcja środowiska :

(Znaczenie: większość odpowiedzi tutaj są w porządku.)

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

Trochę paranoiczna prawda? Możesz zrobić to bardziej gadatliwe, sprawdzając więcej globals.

Ale nie!.

Wszystkie powyższe mogą być sfałszowane/symulowane.

Na przykład, aby sfałszować global obiekt:

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

To nie zostanie dołączone do oryginalnego obiektu globalnego węzła, ale zostanie dołączone do window obiekt w przeglądarce. Oznacza to, że znajdujesz się w Node env w przeglądarce.

Życie jest krótkie!

Czy dbamy o to, czy nasze środowisko jest sfałszowane? To się stanie, gdy jakiś głupi programista zadeklaruje globalną zmienną o nazwie global w globalnym zasięgu. Albo jakiś zły dev w jakiś sposób wstrzykuje kod do naszego env.

Możemy zapobiec wykonaniu naszego kodu, gdy to złapiemy, ale wiele innych zależności naszej aplikacji może zostać w to złapanych. Więc w końcu Kod się złamie. Jeśli kod jest wystarczająco dobry, nie powinieneś dbać o każdy głupi błąd, który mogli zrobić inni.

Co z tego?

If targeting 2 environments: Browser and Node;
"use strict"; i albo po prostu sprawdź window lub global; i wyraźnie zaznacz, że w dokumentach Twój kod obsługuje tylko te środowiska. To jest to!

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

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

Jeśli to możliwe dla Twojego przypadku użycia; zamiast wykrywania środowiska; wykonaj synchroniczne wykrywanie funkcji w bloku try/catch. (te wykonanie zajmie kilka milisekund).

Np.

function isPromiseSupported() {
    var supported = false;
    try {
        var p = new Promise(function (res, rej) {});
        supported = true;
    } catch (e) {}
    return supported;
}
 9
Author: Onur Yıldırım,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-28 19:21:13

A co z użyciem obiektu procesu i sprawdzeniem execPath dla node?

Proces.execPath

To jest absolutna pathname pliku wykonywalnego, który rozpocząłem proces.

Przykład:

/usr / local / bin / node

 4
Author: Kevin Hakanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-21 14:14:02

Jak skrypt może stwierdzić, czy jest wymagany jako moduł commonjs?

Related: aby sprawdzić, czy jest on wymagany jako moduł vs uruchamiany bezpośrednio w węźle, możesz sprawdzić require.main !== module. http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module

 4
Author: Pete,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 17:04:41

Oto moja wariacja na temat tego co jest powyżej:

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

Aby go użyć, zmodyfikuj "House" w drugiej ostatniej linii tak, aby była dowolna nazwa modułu w przeglądarce i opublikuj dowolną wartość modułu (Zwykle konstruktor lub literał obiektu).

W przeglądarkach obiektem globalnym jest window i ma odniesienie do siebie (istnieje okno.window czyli = = window). Wydaje mi się, że jest to mało prawdopodobne, jeśli nie jesteś w przeglądarce lub w środowisku, które chce, abyś uwierzył, że jesteś w przeglądarce. We wszystkich innych przypadkach, jeśli zadeklarowana jest globalna zmienna 'module', używa ona tego, że w przeciwnym razie używa obiektu global.

 4
Author: kybernetikos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-13 13:27:45

Używam process, aby sprawdzić węzeł.js like so

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

Lub

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

Udokumentowane tutaj

 4
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-04 14:14:26

Węzeł.js ma obiekt process, więc dopóki nie masz innego skryptu, który tworzy process, możesz go użyć do określenia, czy kod działa na węźle.

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");
}
 2
Author: Dariusz Sikorski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-13 20:44:21

Jest to dość bezpieczny i prosty sposób zapewnienia zgodności między javascript po stronie serwera i klienta, który będzie również działał z browserify, RequireJS lub CommonJS włączone po stronie klienta:

(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;
}())
 2
Author: Christophe Marois,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-16 14:42:12

Edit : odnośnie Twojego zaktualizowanego pytania: " jak skrypt może stwierdzić, czy jest wymagany jako moduł commonjs?" myślę,że nie może. Możesz sprawdzić, czy exports jest obiektem (if (typeof exports === "object")), ponieważ spec wymaga dostarczenia go do modułów, ale wszystko, co ci mówi, to to ... exports jest obiektem. :-)


Oryginalna odpowiedź:

Jestem pewien, że jest jakiś symbol specyficzny dla NodeJS (EventEmitter, Być może nie, musisz użyć require, aby pobierz Moduł zdarzeń; patrz poniżej ), który możesz sprawdzić, ale jak powiedział David, najlepiej jest wykryć tę funkcję (a nie środowisko), jeśli ma to sens.

Update: może coś w stylu:

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

Ale to po prostu mówi, że jesteś w środowisku z {[5] } i czymś bardzo, bardzo podobnym do Nodejsa Buffer. :-)

 1
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-19 12:19:41

Weź źródło węzła.js I zmienić go, aby zdefiniować zmienną jak runningOnNodeJS. Sprawdź tę zmienną w kodzie.

Jeśli nie możesz mieć własnej prywatnej wersji node.js, Otwórz żądanie funkcji w projekcie. Poproś, aby zdefiniowali zmienną, która daje wersję węzła.js, w którym biegniesz. Następnie sprawdź tę zmienną.

 -1
Author: Aaron Digulla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-19 12:35:12

Bardzo stary post, ale właśnie go rozwiązałem, pakując instrukcje require w try-catch

    try {

           var fs = require('fs')

} catch(e) {
       alert('you are not in node !!!')
}
 -1
Author: Stef de Vries,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 20:32:51