Как проверить, работает ли скрипт под node.Яш?

У меня есть скрипт, который мне нужен от узла.сценарий js, который я хочу сохранить независимым от движка javascript.

Так, например, я хочу сделать:

exports.x = y;

только если он работает в узле.js. как я могу выполнить этот тест?

Edit: при публикации этого вопроса я не знал узел.функция модулей js основана на на CommonJS.

для конкретного примера я дал бы более точный вопрос бывало:

как скрипт может определить, требуется ли он в качестве модуля commonjs?

17 ответов


Это как подчеркивания.js библиотека делает это (ища поддержку CommonJS):

Edit: к вашему обновленному вопросу:

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

пример здесь сохраняет шаблон модуля.


Ну, нет надежного способа обнаружить запуск в узле.js, так как каждый веб-сайт может легко объявить те же переменные, но, поскольку нет window объект в узле.js по умолчанию вы можете пойти другим путем и проверить, работаете ли вы внутри браузера.

это то, что я использую для библиотек, которые должны работать как в браузере, так и под узлом.js:

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

} else {
    window.foo = {};
}

он все еще может взорваться, если это window определяется в узле.js, но нет хороший причина для кого-то сделать это, так как вам явно нужно уходить из var или установите свойство на


проблема с попыткой выяснить, в какой среде работает ваш код, заключается в том, что любой объект может быть изменен и объявлен, что делает почти невозможным выяснить, какие объекты являются родными для среды, и которые были изменены программой.

тем не менее, есть несколько трюков, которые мы можем использовать, чтобы выяснить, в какой среде вы находитесь.

давайте начнем с общепринятого решения, которое используется в подчеркивании библиотека:

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

этот метод на самом деле отлично подходит для серверной стороны, как когда require вызывается функция, она сбрасывает this объект для пустого объекта и переопределяет module для вас снова, то есть вам не нужно беспокоиться о каких-либо внешних вмешательствах. Пока ваш код загружен с помощью require, вы в безопасности.

однако, это разваливается на части в браузере, как любой может легко определить module чтобы казалось, что это объект, который вы ищете. С одной стороны, это может быть поведение, которое вы хотите, но оно также диктует, какие переменные пользователь библиотеки может использовать в глобальной области. Может кто-то хочет использовать переменную с именем module и exports внутри него для другого использования. Маловероятно, но кто мы такие, чтобы судить, какие переменные может использовать кто-то другой, только потому, что другая среда использует это имя переменной?

фишка в том, что если мы предполагаем, что ваш скрипт загруженная в глобальную область (которая будет, если она загружена через тег скрипта) переменная не может быть зарезервирована во внешнем закрытии, потому что браузер этого не позволяет. Теперь помните в узле, то


в настоящее время я наткнулся на неправильное обнаружение узла, который не известно о среде узла в Электрон из-за вводящей в заблуждение функции обнаружения. Следующие решения явно идентифицируют процесс-среду.


Идентифицировать Узел.Яш только

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

это обнаружит, работаете ли вы в узле-процессе, так как process.release содержит "метаданные, связанные с текущей [Node-]release".

после отродьем io.js значение process.release.name может стать io.js (см. процесс-doc). Чтобы правильно определить среду, готовую к узлу, я думаю, вы должны проверить следующее:

определить узел (>= 3.0.0) или io.js

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

этот оператор был протестирован с узлом 5.5.0, Electron 0.36.9 (с узлом 5.1.1) и Chrome 48.0.2564.116.

идентифицировать узел (>= 0.10.0) или Ио.js

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

комментарий@daluege вдохновил меня подумать о более общем доказательстве. Это должно работать от узла.js>= 0.10. Я не нашел уникального идентификатора для предыдущих версий.


P. s.: Я размещаю этот ответ здесь, так как вопрос привел меня сюда, хотя OP искал ответ на другой вопрос.


в браузере работает следующее, если только намеренно, явно не саботируется:

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

БАМ.


большинство предлагаемых решений на самом деле могут быть подделаны. Надежный способ-проверить внутренний Class свойство глобального объекта с помощью Object.prototype.toString. Внутренний класс не может быть подделан в JavaScript:

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

вот довольно классный способ сделать это:

const isBrowser = this.window === this;

это работает, потому что в браузерах глобальная переменная "this" имеет самостоятельную ссылку под названием "window". Эта ссылка на себя не существует в Node.

  • в браузере " это "- это ссылка на глобальный объект, называемый окно''.
  • в узле 'this' есть ссылка на модуль.поставляемый объект.
    • " это " - это не ссылка на глобальный объект узла, называемый "глобальный".
    • " это " - это не ссылка на пространство объявления переменной модуля.

чтобы сломать предложенную выше проверку браузера, вам нужно будет сделать что-то вроде следующего

this.window = this;

перед выполнением проверки.


еще один обнаружение окружающей среды:

(значение: Большинство ответов здесь в порядке.)

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

немного параноик, да? Вы можете сделать это более подробным, проверив больше глобальные.

но не надо!.

все это можно подделать в любом случае имитация.

например, чтобы подделать


Как насчет использования объекта процесса и проверки execPath на node?


как скрипт может определить, требуется ли он в качестве модуля commonjs?

связанный: чтобы проверить, требуется ли это как модуль против запуска непосредственно в узле, вы можете проверить require.main !== module. http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module


вот мой вариант того, что выше:

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

чтобы использовать его, вы изменяете " дом " на второй последней строке, чтобы быть тем, что вы хотите, чтобы имя модуля было в браузере, и публикуете то, что вы хотите, чтобы значение модуля было (обычно конструктор или литерал объекта).

в браузерах глобальный объект является окном, и он имеет ссылку на себя (есть окно.окно, которое = = window). Мне кажется, что это вряд ли произойдет, если вы находитесь в браузере или в среде, которая хочет, чтобы вы верили, что вы в браузере. Во всех остальных случаях, если объявлена глобальная переменная "module", она использует то, что в противном случае она использует глобальный объект.


Я использую process для проверки узла.Яш вот так

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

или

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

документирована здесь


узел.js имеет process объект, пока у вас нет другого скрипта, который создает process вы можете использовать его, чтобы определить, работает ли код на узле.

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

Это довольно безопасный и прямой способ обеспечения совместимости между javascript на стороне сервера и на стороне клиента, который также будет работать с browserify, RequireJS или 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;
}())

редактировать: относительно вашего обновленного вопроса: " как скрипт может сказать, требуется ли он в качестве модуля commonjs?" я не думаю, что это может. Вы можете проверить, является ли exports объект (if (typeof exports === "object")), поскольку спец требует, чтобы он был предоставлен модулям, но все, что говорит вам об этом ... exports - это объект. :-)


оригинальный ответ:

Я уверен, что есть определенный символ NodeJS (EventEmitter, возможно нет, вы должны использовать require чтобы получить модуль Events, см. ниже), которые вы могли бы проверить, но, как сказал Дэвид, в идеале вам лучше обнаружить функцию (а не среду), если это имеет смысл.

обновление: возможно, что-то вроде:

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

но это просто говорит вам, что вы находитесь в среде с require и что-то очень, очень похожее на NodeJS Buffer. :-)


возьмите источник узла.js и измените его, чтобы определить переменную, такую как runningOnNodeJS. Проверьте эту переменную в коде.

Если у вас нет собственной частной версии node.js, откройте запрос функции в проекте. Попросите, чтобы они определили переменную, которая дает вам версию node.js, что вы бежите. Затем проверьте эту переменную.


очень старый пост, но я просто решил его, обернув операторы require в try - catch

    try {

           var fs = require('fs')

} catch(e) {
       alert('you are not in node !!!')
}