Jak sprawdzić, czy skrypt działa w Node.js?

159

Mam skrypt, którego potrzebuję ze skryptu Node.js, który chcę, aby silnik JavaScript był niezależny.

Na przykład chcę to zrobić exports.x = y;tylko wtedy, gdy działa w Node.js. Jak mogę przeprowadzić ten test?


Pisząc to pytanie, nie wiedziałem, że funkcja modułów Node.js jest oparta na CommonJS .

W przypadku konkretnego przykładu, który podałem, dokładniejsze pytanie brzmiałoby:

W jaki sposób skrypt może stwierdzić, czy był wymagany jako moduł CommonJS?

theosp
źródło
3
Nie mam pojęcia, dlaczego próbujesz to zrobić, ale z reguły powinieneś używać wykrywania funkcji, a nie wykrywania silnika. quirksmode.org/js/support.html
Quentin,
4
W rzeczywistości jest to prośba o zaimplementowanie wykrywania funkcji, ale pytanie jest słabo opisane.
monokrom
opublikowałem bibliotekę na własny użytek, pomoże to pomoże npmjs.com/package/detect-is-node
abhirathore2006
Jednym z problemów z tym pytaniem i większością odpowiedzi jest założenie, że istnieją tylko dwie możliwości: przeglądarka lub Node.js. Istnieje możliwość, że nie jest to ani przeglądarka, ani Node.js, jak w przypadku Oracle Java Nashorn. Jeśli pakiet JDK jest zainstalowany, komenda jjs umożliwia uruchamianie skryptów. Ale istnieje wiele różnic między Nashorn i Node.js, więc nie można nic założyć. A kto wie, jakie opcje przyniesie przyszłość? Potrzebne jest wykrywanie funkcji.

Odpowiedzi:

80

Szukając wsparcia CommonJS , robi to biblioteka Underscore.js :

Edytuj: do 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 wzorzec Module.

Ross
źródło
45
Wykrywa to obsługę CommonJS, którą mogą obsługiwać przeglądarki.
mikemaccana
7
Tu jest problem i gwoździarka „przybiła”. Próbuję CommonJS w przeglądarce, a moduł ładujący, którego używam, definiuje module.exports, więc to rozwiązanie niepoprawnie powiedziałoby mi, że jestem w węźle.
Mark Melville
1
@MarkMelville prawdopodobnie o to właśnie prosi PO, więc nie stanowi to problemu .
Ross
13
Słabe sformułowanie z mojej strony. Chodzi mi o to, że jest problem z tym rozwiązaniem. OP mógł to zaakceptować, ale ja nie.
Mark Melville,
7
Z pewnością NIE jest to najlepsza udzielona odpowiedź.
user3751385
107

Cóż, nie ma niezawodnego sposobu na wykrycie działania w Node.js, ponieważ każda witryna może łatwo zadeklarować te same zmienne, ale ponieważ windowdomyślnie nie ma obiektu w Node.js, możesz przejść na odwrót i sprawdzić, czy działasz w Przeglądarka.

Oto, czego używam w przypadku bibliotek, które powinny działać zarówno w przeglądarce, jak i pod Node.js:

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

} else {
    window.foo = {};
}

Może nadal wybuchnąć w przypadku, gdy windowjest to zdefiniowane w Node.js, ale nie ma dobrego powodu, aby ktoś to zrobił, ponieważ jawnie musiałbyś opuścić varlub ustawić właściwość globalobiektu.

EDYTOWAĆ

Aby wykryć, czy Twój skrypt był wymagany jako moduł CommonJS, znowu nie jest to łatwe. Jedyną rzeczą, którą commonJS określa, jest to, że A: moduły zostaną dołączone poprzez wywołanie funkcji, requirea B: moduły eksportują rzeczy poprzez właściwości exportsobiektu. Teraz, jak to jest zaimplementowane, pozostawiono systemowi bazowemu. Node.js opakowuje zawartość modułu w anonimową funkcję:

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

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

Ale nie próbuj tego wykrywać za pomocą jakichś szalonych arguments.callee.toString()rzeczy, zamiast tego użyj mojego przykładowego kodu powyżej, który sprawdza przeglądarkę. Node.js jest o wiele czystszym środowiskiem, więc jest mało prawdopodobne, że windowzostanie tam zadeklarowany.

Ivo Wetzel
źródło
2
O „Node.js to o wiele czystsze środowisko, więc jest mało prawdopodobne, że okno zostanie tam zadeklarowane.”: Cóż, właśnie przyszedłem tutaj, szukając sposobu, aby dowiedzieć się, czy mój skrypt działa w przeglądarce emulowanej przez node.js + JSDOM lub w zwykłej przeglądarce ... Powodem jest to, że mam nieskończoną pętlę za pomocą setTimeout do sprawdzenia lokalizacji adresu URL, co jest w porządku w przeglądarce, ale utrzymuje skrypt node.js działający na zawsze ... Więc może być okno w końcu w skrypcie node.js :)
Eric Bréchemier
1
@Eric Bardzo wątpię, że będzie w zasięgu globalnym, więc jeśli nie zaimportujesz czegoś tak jak windoww pierwszej linii swojego modułu, nie powinieneś mieć żadnych problemów. Możesz również uruchomić anonimową funkcję i sprawdzić jej [[Class]]zawartość this(działa tylko w trybie nieścisłości
Ivo Wetzel
1
Mój problem różni się nieco od OP: nie potrzebuję skryptu, jest ładowany przez JSDOM z emulowanym oknem jako kontekstem globalnym ... Nadal jest uruchamiany przez node.js + V8, tylko w innym kontekście niż zwykłe moduły.
Eric Bréchemier
1
Prawdopodobnie ... Poszedłem w innym kierunku: 1) wykryć wsparcie dla onhashchange („onhashchange” w oknie), aby uniknąć tworzenia nieskończonej pętli 2) symulować wsparcie poprzez ustawienie właściwości onhashchange w emulowanym oknie w głównym skrypcie node.js.
Eric Bréchemier
1
typeof self === 'object'może być bezpieczniejsze, ponieważ typeof window === 'undefined'nie działa w zakresie pracowników sieci Web.
Lewis
45

Obecnie natknąłem się na niewłaściwe wykrywanie węzła, który nie jest świadomy środowiska węzła w Electron z powodu wprowadzającego w błąd wykrywania funkcji. Poniższe rozwiązania jednoznacznie identyfikują środowisko procesowe.


Zidentyfikuj tylko Node.js.

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

Pozwoli to wykryć, czy pracujesz w procesie Node, ponieważ process.releasezawiera „metadane związane z bieżącą wersją [Node-]”.

Po pojawieniu się io.js wartość process.release.namemoże się również zmienićio.js (zobacz dokumentację procesu ). Aby poprawnie wykryć środowisko gotowe do węzła, należy sprawdzić, co następuje:

Zidentyfikuj węzeł (> = 3.0.0) lub 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 rozważenia bardziej ogólnego dowodu. To powinno działać z Node.js> = 0,10 . Nie znalazłem unikalnego identyfikatora dla poprzednich wersji.


Ps: Umieszczam tę odpowiedź tutaj, ponieważ pytanie mnie tutaj prowadzi, chociaż OP szukał odpowiedzi na inne pytanie.

Florian Breisch
źródło
2
To wydaje się być zdecydowanie najbardziej niezawodnym podejściem, dziękuję. Chociaż działa tylko dla wersji> = 3.0.0.
filip
@daluege - dzięki za inspirację. Niestety nie znalazłem dowodu na mniej niż 0,10.
Florian Breisch,
3
Znalazłem korzystanie z React webpack processi process.versionistnieje w pakiecie, więc dodałem dodatkowe sprawdzenie, process.versiongdzie process.release.nodejest niezdefiniowane po stronie klienta, ale ma wersję węzła jako wartość po stronie serwera
Aaron
@Aaron: dzięki za wskazówkę. Nie udało mi się znaleźć żadnej definicji process.versionzmiennej (w React, WebPack lub React-Webpack). Byłbym wdzięczny za każdą wskazówkę, w której zdefiniowano zmienną wersji, aby dodać ją do odpowiedzi. W zależności od ograniczeń release.node do węzła> = 3.xx
Florian Breisch
2
function isNodejs() { return typeof "process" !== "undefined" && process && process.versions && process.versions.node; }
Jednowierszowy
25

Problem z próbą ustalenia, w jakim środowisku działa twój kod, polega na tym, że każdy obiekt można zmodyfikować i zadeklarować, co sprawia, że ​​ustalenie, które obiekty są natywne dla środowiska, a które zostały zmodyfikowane przez program, jest prawie niemożliwe.

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

Zacznijmy od ogólnie przyjętego rozwiązania używanego w bibliotece podkreślników:

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

Ta technika jest w rzeczywistości idealna dla serwera, ponieważ gdy requirewywoływana jest funkcja, resetuje thisobiekt do pustego obiektu i ponownie definiuje moduledla Ciebie, co oznacza, że ​​nie musisz się martwić o jakiekolwiek ingerencje z zewnątrz. 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ć, moduleaby wyglądał, jakby to był obiekt, którego szukasz. Z jednej strony może to być zachowanie, które chcesz, ale określa również, jakich zmiennych użytkownik biblioteki może używać w zakresie globalnym. Może ktoś chce użyć zmiennej z nazwą module, która się exportsw niej znajduje, do innego użytku. Jest 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 założymy, że twój skrypt jest ładowany w zasięgu globalnym (co będzie, jeśli będzie ładowany przez tag skryptu), zmienna nie może być zarezerwowana w zewnętrznym zamknięciu, ponieważ przeglądarka na to nie pozwala . Teraz pamiętaj, że w węźle thisobiekt jest pustym obiektem, ale modulezmienna jest nadal dostępna. To dlatego, że jest zadeklarowany w zewnętrznym zamknięciu. Więc możemy następnie naprawić kontrolę podkreślenia, dodając dodatkową kontrolę:

this.module !== module

Dzięki temu, jeśli ktoś zadeklaruje modulew zasięgu globalnym w przeglądarce, zostanie on umieszczony w thisobiekcie, co spowoduje niepowodzenie testu, ponieważ this.modulebędzie to ten sam obiekt co module. W węźle this.modulenie istnieje i moduleistnieje w zewnętrznym zamknięciu, więc test powiedzie się, ponieważ nie są równoważne.

Tak więc ostateczny test to:

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

Uwaga: Chociaż pozwala to teraz na moduleswobodne używanie zmiennej w zakresie globalnym, nadal można to ominąć w przeglądarce, tworząc nowe zamknięcie i deklarując modulew nim, a następnie ładując skrypt w tym zamknięciu. W tym momencie użytkownik w pełni replikuje środowisko węzłów i miejmy nadzieję, że wie, co robi i próbuje spełnić wymagania stylu węzła. Jeśli kod jest wywoływany w tagu skryptu, nadal będzie zabezpieczony przed nowymi zewnętrznymi zamknięciami.

Czas
źródło
2
Wow, dziękuję za jasne wyjaśnienie powodów stojących za każdym kawałkiem twojej jednej linijki.
Jon Coombs
otrzymałem, Cannot read property 'module' of undefinedponieważ jest to nieokreślone na przykład w testach
mokki
20

Poniższe działa w przeglądarce, chyba że celowo, jawnie sabotowane:

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

Bam.

user3751385
źródło
4
var proces = {toString: function () {return '[proces obiektu]'; }};
Nick Desaulniers
1
Czy jest jakiś powód, dla którego używasz process+''zamiast process.toString()?
harmic
3
Prawie. Użyj tego zamiast:Object.prototype.toString.call(process)
sospedra
2
To najlepsza odpowiedź na to pytanie.
loretoparisi
3
@harmic: var process = null;spowodowałoby niepowodzenie drugiego przypadku. Zarówno w Javascript, jak i w Javie wyrażenie '' + xdaje to samo, x.toString()z wyjątkiem sytuacji, gdy xjest nieprzyjemne, pierwsze generuje "null"lub "undefined"gdy drugie zgłosi błąd.
joeytwiddle
17

Oto całkiem fajny sposób, aby to zrobić:

const isBrowser = this.window === this;

To działa, ponieważ w przeglądarkach globalna zmienna „this” ma odniesienie do siebie zwane „window”. To odniesienie do siebie nie istnieje w Node.

  • W przeglądarce „to” jest odniesieniem do obiektu globalnego, zwanego „oknem”.
  • W węźle „this” jest odniesieniem do obiektu module.exports.
    • „this” nie jest odniesieniem do globalnego obiektu Node, zwanego „global”.
    • „this” nie jest odniesieniem do przestrzeni deklaracji zmiennej modułu.

Aby złamać powyższe sugerowane sprawdzenie przeglądarki, musisz wykonać coś podobnego do poniższego

this.window = this;

przed wykonaniem sprawdzenia.

Patrick
źródło
Dlaczego nie po prostu const isBrowser = this.window !== undefined? Teoretycznie w węźle mogę zrobić, this.window = thisaby oszukać rozwiązanie.
Tyler Long
11

Jeszcze jedno wykrycie środowiska :

(Znaczenie: większość odpowiedzi jest 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ę paranoicznie, prawda? Możesz uczynić to bardziej szczegółowym, sprawdzając więcej elementów globalnych .

Ale NIE !.

Wszystko to i tak można sfałszować / zasymulować.

Na przykład, aby sfałszować globalobiekt:

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

Nie zostanie to dołączone do oryginalnego obiektu globalnego węzła, ale zostanie dołączone do windowobiektu w przeglądarce. Oznacza to, że jesteś w Node env w przeglądarce.

Życie jest krótkie!

Czy obchodzi nas, czy nasze środowisko jest fałszywe? Stałoby się tak, gdyby jakiś głupi programista zadeklarował zmienną globalną o nazwie globalw zasięgu globalnym. Albo jakiś zły programista w jakiś sposób wstrzykuje kod do naszego pliku env.

Możemy uniemożliwić wykonanie naszego kodu, gdy to złapiemy, ale może to spowodować wiele innych zależności naszej aplikacji. W końcu kod się zepsuje. Jeśli twój kod jest wystarczająco dobry, nie powinieneś przejmować się każdym głupim błędem, który mógł popełnić ktoś inny.

Więc co?

W przypadku kierowania na 2 środowiska: przeglądarka i węzeł;
"use strict"; i albo po prostu sprawdź windowlub global; i wyraźnie wskaż, że w dokumentach Twój kod obsługuje tylko te środowiska. Otóż ​​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; wykonuje synchroniczne wykrywanie funkcji w bloku try / catch. (ich wykonanie zajmie kilka milisekund).

na przykład

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

Większość proponowanych rozwiązań faktycznie można sfałszować. Solidnym sposobem jest sprawdzenie wewnętrznej Classwłaściwości obiektu globalnego przy użyciu rozszerzenia Object.prototype.toString. Klasy wewnętrznej nie można sfałszować w JavaScript:

var isNode = 
    typeof global !== "undefined" && 
    {}.toString.call(global) == '[object global]';
Fabian Jakobs
źródło
2
Stanie się to prawdą w ramach browserify.
alt
1
Czy to przetestowałeś? Nie widzę, jak browserify może zmienić wewnętrzną klasę obiektu. Wymagałoby to zmiany kodu w maszynie wirtualnej JavaScript lub nadpisania, Object.prototype.toStringco jest naprawdę złą praktyką.
Fabian Jakobs
Przetestowałem to. Oto co robi browserify: var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
Vanuan
Widzisz, w Chrome ({}.toString.call(window))jest równy "[object global]".
Vanuan
2
To dziwne, ponieważ window.toString()produkuje"[object Window]"
Vanuan
5

Co na temat korzystania z obiektu procesu i sprawdzania execPath za node?

process.execPath

To jest bezwzględna ścieżka do pliku wykonywalnego, który rozpoczął proces.

Przykład:

/ usr / local / bin / node

Kevin Hakanson
źródło
2
O co chodzi window.process = {execPath: "/usr/local/bin/node"};?
Константин Ван
4

Oto moja odmiana tego, co 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 drugim ostatnim wierszu tak, aby była dowolną nazwą modułu w przeglądarce i opublikuj jakąkolwiek chcesz wartość modułu (zwykle konstruktor lub literał obiektu ).

W przeglądarkach globalnym obiektem jest window i ma odniesienie do samego siebie (jest window.window, które jest == window). Wydaje mi się, że jest to mało prawdopodobne, chyba że jesteś w przeglądarce lub w środowisku, które chce, abyś uwierzył, że jesteś w przeglądarce. We wszystkich innych przypadkach, jeśli istnieje zadeklarowana globalna zmienna „moduł”, używa jej, w przeciwnym razie używa obiektu globalnego.

kybernetikos
źródło
4

Używam processdo sprawdzenia node.js w ten sposób

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

Chris
źródło
2
process.titlemożna zmienić
Ben Barkay
Następnie sprawdź tytuł, na który go zmieniłeś. Lub użyj process.version
Chris
Jeśli piszesz dla biblioteki (tak jak powinieneś), nie będziesz w stanie oczekiwać, jaki powinien być tytuł
Ben Barkay
3

W chwili pisania tego artykułu ta odpowiedź jest raczej opcją „wkrótce”, ponieważ wykorzystuje bardzo nowe funkcje JavaScript.

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

runtimeWartość będzie albo nodealbo not node.

Jak wspomniano, zależy to od kilku nowych funkcji JavaScript. globalThisto sfinalizowana funkcja w specyfikacji ECMAScript 2020. Opcjonalne łączenie łańcuchowe / zerowe łączenie ( ?część globalThis.process?.release?.name) jest obsługiwane w silniku V8, który jest dostarczany z Chrome 80. Od 08.04.2020 ten kod będzie działał w przeglądarce, ale nie będzie działał w Node, ponieważ gałąź Node 13 używa V8 7.9.xxx. Uważam, że Node 14 (ma zostać wydany 21.04.2020) ma używać V8 8.x +.

Takie podejście wiąże się ze sporą dawką obecnych ograniczeń. Jednak; tempo, w jakim publikowane są przeglądarki / węzeł, ostatecznie będzie niezawodnym, jednolinijkowym.

Corey
źródło
1
To powinna być akceptowana odpowiedź! i wszyscy powinni używać węzła 14 btw
Sceat
2

Node.js ma processobiekt, więc jeśli nie masz żadnego innego skryptu, który go tworzy, processmożesz go użyć do określenia, czy kod działa w 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
źródło
2

Jest to całkiem bezpieczny i prosty sposób na zapewnienie kompatybilności między javascriptem po stronie serwera i klienta, który będzie również działał z zawartymi po stronie klienta browserify, RequireJS lub CommonJS:

(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
źródło
1

Edycja : W odniesieniu do zaktualizowanego pytania: „W jaki sposób skrypt może stwierdzić, czy był wymagany jako moduł commonjs?” Myślę, że nie może. Możesz sprawdzić, czy exportsjest to obiekt ( if (typeof exports === "object")), ponieważ specyfikacja wymaga, aby była dostarczana do modułów, ale jedyne, co ci mówi, to to, że ... exportsjest obiektem. :-)


Oryginalna odpowiedź:

Jestem pewien, że istnieje jakiś symbol specyficzny dla NodeJS ( EventEmitterbyć może nie, musisz go użyć, requireaby pobrać moduł zdarzeń; patrz poniżej ), który możesz sprawdzić, ale jak powiedział David, najlepiej byłoby, gdybyś wykrył tę funkcję (raczej niż środowisko), jeśli ma to jakiś sens.

Aktualizacja : Może coś takiego:

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

Ale to tylko mówi ci, że jesteś w środowisku z requireczymś bardzo, bardzo podobnym do NodeJS Buffer. :-)

TJ Crowder
źródło
Nadal mogę to zepsuć, ustawiając wszystkie te rzeczy na stronie internetowej ... to po prostu przesada;) Sprawdzanie, czy jesteś w przeglądarce, jest łatwiejsze, ponieważ środowisko Node jest czystsze.
Ivo Wetzel
1
@Ivo: Tak, zobacz moje ostatnie zdanie. windowRównie łatwo mogę złamać Twój czek, definiując zmienną w aplikacji NodeJS. :-)
TJ Crowder
1
@Ivo: Nie zdziwiłbym się wcale, gdyby ktoś zdefiniował windoww module NodeJS, więc mógłby dołączyć kod, który windowbył obiektem globalnym i nie chciał modyfikować tego kodu. Ja bym tego nie zrobił, ty nie, ale założę się, że ktoś to zrobił. :-) Albo po prostu mieli windowna myśli coś zupełnie innego.
TJ Crowder
1
@Ivo: yuiblog.com/blog/2010/04/09/… jest jednym z powodów, dla których obiekt okna może być zdefiniowany w node.js
slebetman
1
@TJCrowdertypeof process !== "undefined" && process.title === "node"
Raynos
0
const isNode =
  typeof process !== 'undefined' &&
  process.versions != null &&
  process.versions.node != null;
BAR
źródło
-1

Weź źródło node.js i zmień je, aby zdefiniować zmienną, taką jak runningOnNodeJS. Sprawdź tę zmienną w swoim 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 podaje wersję node.js, w której pracujesz. Następnie sprawdź tę zmienną.

Aaron Digulla
źródło
1
To znowu nie rozwiązuje jego (w zasadzie nierozwiązywalnego) problemu, znowu mogę po prostu stworzyć taką zmienną w przeglądarce. Lepszym sposobem byłoby uniemożliwienie skryptom tworzenia windowglobalnego, zgaduję, że złożę wniosek o funkcję w tym.
Ivo Wetzel
@Ivo: To zły pomysł, który złamałby kod, który używa jsdom ( github.com/tmpvar/jsdom ) do manipulacji domenami po stronie serwera przy użyciu znanych bibliotek, takich jak YUI i jQuery. Obecnie produkowany jest kod, który to robi.
slebetman
@slebetman Nie, to nie złamie jsdom. Mówię o global , tak jak w żadnej instrukcji var global , przykładowy kod tam używa varinstrukcji, ludzie, którzy po prostu przeciekają do globalnej przestrzeni nazw, cóż, nie rozumieją wtedy koncepcji samodzielnych modułów
Ivo Wetzel
@Ivo to trochę brutalne, to tak, jakbyśmy mówili, że powinniśmy jeść ciastka, ponieważ ludzie je przejadają. Ci muszą zaśmiecać globalnej przestrzeni nazw, aby osiągnąć bibliotekę, która będzie działać między moduł. Albo możesz zawinąć to wszystko w jeden moduł, ale w takim razie o co chodzi?
Ben Barkay,
-1

Bardzo stary post, ale właśnie go rozwiązałem, opakowując wymagane instrukcje w próbkę

try {
     var fs = require('fs')
} catch(e) {
     alert('you are not in node !!!')
}
Stef de Vries
źródło
2
To nieprawda, możesz użyć browserify, aby użyć wywołań „nodeish” require ()
gruby