work unexpected nodejs node modules instead how exports es6 doesn javascript node.js commonjs

javascript - nodejs - node js unexpected identifier



¿Cómo verificar si un script se está ejecutando bajo node.js? (17)

¿Cómo puede un script decir si se ha requerido como un módulo commonjs?

Relacionado: para comprobar si se ha requerido como un módulo vs ejecutar directamente en el nodo, puede comprobar require.main !== module . http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module

Tengo un script que estoy solicitando de un script node.js, que quiero mantener el motor de JavaScript independiente.

Entonces, por ejemplo, quiero hacer:

exports.x = y;

solo si se está ejecutando bajo node.js. ¿cómo puedo realizar esta prueba?

Editar: Al publicar esta pregunta, no sabía que la función de módulos node.js se basa en commonjs .

Para el ejemplo específico que di una pregunta más precisa, habría sido:

¿Cómo puede un script decir si se ha requerido como un módulo commonjs?


¿Qué pasa con el uso del objeto de proceso y la comprobación de execPath para el node ?

process.execPath

Esta es la ruta de acceso absoluta del ejecutable que inició el proceso.

Ejemplo:

/ usr / local / bin / node


Aquí está mi variación sobre lo que está arriba:

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

Para usarlo, modifique la "Casa" en la segunda última línea para que sea lo que quiera que el nombre del módulo esté en el navegador y publique lo que quiera que sea el valor del módulo (generalmente un constructor o un objeto literal) )

En los navegadores, el objeto global es la ventana, y tiene una referencia a sí mismo (hay una ventana.ventana que es == ventana). Me parece que es poco probable que esto ocurra a menos que esté en un navegador o en un entorno que quiera que crea que está en un navegador. En todos los demás casos, si hay una variable global de ''módulo'' declarada, usa eso, de lo contrario, usa el objeto global.


Aquí hay una forma genial de hacerlo también:

const isBrowser = this.window === this;

Esto funciona porque en los navegadores la variable global ''this'' tiene una autorreferencia llamada ''ventana''. Esta autorreferencia no existe en Node.

  • En el navegador ''this'' es una referencia al objeto global, llamado ''ventana''.
  • En el nodo ''this'' es una referencia al objeto module.exports.
    • ''esto'' no es una referencia al objeto global Node, llamado ''global''.
    • ''esto'' no es una referencia al espacio de declaración de variables del módulo.

Para romper el control de navegador sugerido anteriormente, tendría que hacer algo como lo siguiente

this.window = this;

antes de ejecutar el cheque.


Así es como lo hace la biblioteca Underscore.js (buscando el soporte CommonJS):

Editar: a su pregunta actualizada:

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

El ejemplo aquí conserva el patrón de Módulo.


Bueno, no hay una manera confiable de detectar la ejecución en Node.js ya que cada sitio web podría declarar fácilmente las mismas variables, sin embargo, dado que no hay ningún objeto de window en Node.js de manera predeterminada, puede ir al revés y verificar si se está ejecutando dentro un navegador.

Esto es lo que uso para libs que deberían funcionar tanto en un navegador como en Node.js:

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

Todavía podría explotar en caso de que esa window esté definida en Node.js, pero no hay una buena razón para que alguien haga esto, ya que explícitamente deberá dejar de lado var o establecer la propiedad en el objeto global .

EDITAR

Para detectar si su script ha sido requerido como un módulo CommonJS, de nuevo no es fácil. Lo único que commonJS especifica es que A: los módulos se incluirán a través de una llamada a la función require y B: los módulos exportan cosas a través de propiedades en el objeto de exports . Ahora cómo se implementa eso se deja al sistema subyacente. Node.js envuelve el contenido de los módulos en una función anónima.

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

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

Pero no vaya allí intentando detectar eso a través de algunas cosas locas de arguments.callee.toString() , en su lugar solo use mi código de ejemplo anterior que comprueba el navegador, Node.js es un entorno mucho más limpio, por lo que es poco probable que la window haga. ser declarado allí.


El problema al tratar de averiguar en qué entorno se está ejecutando su código es que cualquier objeto puede modificarse y declararse, lo que hace casi imposible determinar qué objetos son nativos del entorno y cuáles han sido modificados por el programa.

Sin embargo, hay algunos trucos que podemos usar para averiguar con certeza en qué entorno se encuentra.

Comencemos con la solución generalmente aceptada que se usa en la biblioteca de guiones bajos:

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

Esta técnica en realidad está perfectamente bien para el lado del servidor, ya que cuando se llama a la función require , restablece el objeto a un objeto vacío y redefine el module nuevamente, lo que significa que no tiene que preocuparse por ninguna alteración externa. Siempre que su código se cargue con require , estará a salvo.

Sin embargo, esto se desmorona en el navegador, ya que cualquiera puede definir fácilmente el module para que parezca que es el objeto que está buscando. Por un lado, este podría ser el comportamiento que desea, pero también dicta qué variables puede usar el usuario de la biblioteca en el ámbito global. Tal vez alguien quiera usar una variable con el module nombre que tiene exports dentro para otro uso. Es poco probable, pero ¿quiénes somos para juzgar qué variables puede usar otra persona, simplemente porque otro entorno usa ese nombre de variable?

El truco, sin embargo, es que si asumimos que su script se está cargando en el ámbito global (que será si se carga mediante una etiqueta de script) una variable no se puede reservar en un cierre externo, porque el navegador no permite eso . Ahora recuerde en el nodo, this objeto es un objeto vacío, sin embargo, la variable del module todavía está disponible. Eso es porque está declarado en un cierre exterior. Entonces podemos corregir el cheque de subrayado agregando un cheque adicional:

this.module !== module

Con esto, si alguien declara un module en el alcance global del navegador, se colocará en this objeto, lo que hará que la prueba falle, porque this.module será el mismo objeto que el módulo. En el nodo, this.module no existe, y el module existe dentro de un cierre externo, por lo que la prueba tendrá éxito, ya que no son equivalentes.

Por lo tanto, la prueba final es:

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

Nota: Si bien esto permite ahora que la variable de module se use libremente en el ámbito global, aún es posible omitir esto en el navegador creando un nuevo module cierre y declaración dentro de ese, y luego cargando el script dentro de ese cierre. En ese momento, el usuario está replicando por completo el entorno del nodo y, con un poco de suerte, sabe lo que está haciendo e intenta hacer que un estilo de nodo lo requiera. Si se llama al código en una etiqueta de script, seguirá a salvo de cualquier nuevo cierre externo.


En la actualidad tropecé con una detección incorrecta de Nodo que no tiene conocimiento del entorno del nodo en el Electron debido a una detección de funciones engañosa. Las siguientes soluciones identifican explícitamente el proceso-entorno.

Identificar solamente Node.js

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

Esto descubrirá si se está ejecutando en un proceso de nodo, ya que process.release contiene los "metadatos relacionados con la versión actual [Node-]".

Después de la io.js de io.js el valor de process.release.name también puede convertirse en io.js (ver process-doc ). Para detectar adecuadamente un entorno preparado para Nodo, supongo que debe verificar lo siguiente:

Identificar nodo (> = 3.0.0) o io.js

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

Esta afirmación se probó con el nodo 5.5.0, Electron 0.36.9 (con el nodo 5.1.1) y Chrome 48.0.2564.116.

Identificar nodo (> = 0.10.0) o io.js

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

El comentario de @ daluege me inspiró a pensar en una prueba más general. Esto debería funcionar desde Node.js> = 0.10 . No encontré un identificador único para versiones anteriores.

PD: Estoy publicando esa respuesta aquí ya que la pregunta me llevó hasta aquí, aunque el OP estaba buscando una respuesta a una pregunta diferente.


Esta es una forma bastante segura y directa de garantizar la compatibilidad entre javascript del lado del servidor y del lado del cliente, que también funcionará con browserify, RequireJS o CommonJS incluidos en el lado del cliente:

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


Estoy usando el process para comprobar node.js como tal

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

o

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

Documentado here


La mayoría de las soluciones propuestas en realidad pueden ser falsificadas. Una forma sólida es verificar la propiedad Class interna del objeto global utilizando Object.prototype.toString . La clase interna no se puede fingir en JavaScript:

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


Lo siguiente funciona en el navegador a menos que intencionalmente, saboteado explícitamente:

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

Bam.


Node.js tiene un objeto de process , por lo que siempre que no tenga ningún otro script que cree un process , puede usarlo para determinar si el código se ejecuta en 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"); }


Publicación muy antigua, pero acabo de solucionarla al envolver las declaraciones requeridas en un try - catch

try { var fs = require(''fs'') } catch(e) { alert(''you are not in node !!!'') }


Sin embargo, otra detección de ambiente :

(Significado: la mayoría de las respuestas aquí están bien.)

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 poco paranoico ¿verdad? Puede hacer que esto sea más detallado al comprobar si hay más elementos globals .

¡Pero NO!

Todos estos anteriores pueden ser simulados / falsos de todos modos.

Por ejemplo, para simular el objeto global :

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

Esto no se adjuntará al objeto global original del Nodo, pero se adjuntará al objeto window en un navegador. Entonces implicará que estás en Node env dentro de un navegador.

¡La vida es corta!

¿Nos importa si nuestro entorno es falso? Sucedería cuando algún desarrollador estúpido declare una variable global llamada global en el alcance global. O algún dev malvado inyecta código en nuestro env de alguna manera.

Podemos evitar que nuestro código se ejecute cuando captemos esto, pero muchas otras dependencias de nuestra aplicación podrían quedar atrapadas en esto. Entonces eventualmente el código se romperá. Si su código es lo suficientemente bueno, no debería preocuparse por todos y cada uno de los errores tontos que podrían haber cometido otros.

¿Y qué?

Si se orienta a 2 entornos: navegador y nodo;
"use strict" ; y simplemente verifique por window o global ; e indique claramente que en los documentos su código solo admite estos entornos. ¡Eso es!

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

Si es posible para su caso de uso; en lugar de detección del entorno; hacer detección de características sincrónicas dentro de un bloque try / catch. (estos tardarán unos milisegundos en ejecutarse).

p.ej

function isPromiseSupported() { var supported = false; try { var p = new Promise(function (res, rej) {}); supported = true; } catch (e) {} return supported; }


Tome la fuente de node.js y cámbiela para definir una variable como runningOnNodeJS . Verifique esa variable en su código.

Si no puede tener su propia versión privada de node.js, abra una solicitud de función en el proyecto. Pídales que definan una variable que le proporcione la versión de node.js en la que se está ejecutando. Luego, verifique esa variable.


Editar : Con respecto a su pregunta actualizada: "¿Cómo puede un script decir si se ha requerido como un módulo de Commonjs?" No creo que pueda Puede verificar si las exports son un objeto ( if (typeof exports === "object") ), ya que la especificación requiere que se proporcione a los módulos, pero todo lo que le dice es que ... exports es un objeto. :-)

Respuesta original:

Estoy seguro de que hay algún símbolo específico de EventEmitter ( EventEmitter , tal vez no, debes usar require para obtener el módulo de eventos, ver abajo ) que podrías verificar, pero como dijo David, lo ideal es que detectes la función (en lugar de entorno) si tiene sentido hacerlo.

Actualización : Tal vez algo así como:

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

Pero eso solo te dice que estás en un entorno con necesidades y algo muy, muy parecido al Buffer de NodeJS. :-)