Cliente en Node.js: Error de referencia no detectado: require no está definido

433

Estoy escribiendo una aplicación con la combinación Node.js, Express.js y Jade .

Tengo un archivo client.jsque se carga en el cliente. En ese archivo tengo un código que llama a funciones de otros archivos JavaScript. Mi intento fue usar

var m = require('./messages');

para cargar el contenido de messages.js(al igual que lo hago en el lado del servidor) y luego llamar a las funciones de ese archivo. Sin embargo, requireno está definido en el lado del cliente y arroja un error del formulario Uncaught ReferenceError: require is not defined.

Estos otros archivos JavaScript también se cargan en tiempo de ejecución en el cliente, porque coloco los enlaces en el encabezado de la página web. Entonces el cliente conoce todas las funciones que se exportan desde estos otros archivos.

¿Cómo llamo a estas funciones desde estos otros archivos JavaScript (como messages.js) en el client.jsarchivo principal que abre el socket al servidor?

4
  • 5
    ¿Por qué no los <script src="messages.js"></script>llamas después de eso? 27/0913 a las 20:34
  • 1
    Quizás esto pueda ser una solución, pero hay otra cosa que me preocupa. También tengo un archivo llamado "representacion.js" para abstraer la representación que es común al cliente y al servidor. En ese archivo también tengo declaraciones require y en el lado del servidor debería estar bien porque estoy ejecutando node. Sin embargo, del lado del cliente esto será un problema. ¿Qué piensas? 27 de septiembre de 2013 a las 20:45
  • 2
    Para los novatos como yo (¡que ni siquiera podía deletrear "npm" hace una semana! :-), puede ser útil comprender que la --requireopción de browserify require()se define en el lado del cliente. Ver: lincolnloop.com/blog/speedy-browserifying-multiple-bundles 12 mar 16 a las 18:34
  • 2
    @Sterling Archer ... Si hay 100 archivos de este tipo ... no podemos seguir cargando, en HTML correcto ......... 9 de junio de 2016 a las 18:58
529

Esto se debe a require()que no existe en el navegador / JavaScript del lado del cliente.

Ahora tendrá que tomar algunas decisiones sobre la administración de scripts de JavaScript del lado del cliente.

Tienes tres opciones:

  1. Usa la <script>etiqueta.
  2. Utilice una implementación de CommonJS . Tiene dependencias sincrónicas como Node.js
  3. Utilice una implementación de definición de módulo asincrónico (AMD).

Las implementaciones del lado del cliente de CommonJS incluyen (la mayoría de ellas requieren un paso de compilación antes de implementar):

  1. Browserify : puede usar la mayoría de los módulos de Node.js en el navegador. Este es mi favorito personal.
  2. Webpack : lo hace todo (paquetes de código JavaScript, CSS, etc.). Se hizo popular por el surgimiento de React, pero es conocido por su difícil curva de aprendizaje.
  3. Rollup : un nuevo contendiente. Aprovecha los módulos ES6 e incluye capacidades de agitación de árboles (elimina el código no utilizado).

Puede leer más sobre mi comparación de Browserify vs Componente (obsoleto) .

Las implementaciones de AMD incluyen:

  1. RequireJS : muy popular entre los desarrolladores de JavaScript del lado del cliente. No es de mi gusto por su naturaleza asincrónica.

Tenga en cuenta que en su búsqueda para elegir con cuál ir, leerá sobre Bower . Bower es solo para dependencias de paquetes y no tiene opiniones sobre definiciones de módulos como CommonJS y AMD.

13
  • 2
    Muchísimas gracias. Hice una mini prueba por separado, por eso me tomó un tiempo responder. Es posible que vuelva con algunas preguntas en unos minutos solo para asegurarme de que entiendo cómo funcionó esta magia. Solo quiero juntar todo. Gracias de nuevo. ¡Browserify parece rockear! :) 27 de septiembre de 2013 a las 21:18
  • 6
    Creo que JSPM debería agregarse a la lista.
    Martijn
    11/02/2016 a las 9:12
  • 54
    ¿Podría obtener un ejemplo del uso de la <script>etiqueta para importar una clase React sin el uso de un administrador de paquetes nodeJs? 12 de mayo de 2016 a las 16:50
  • 2
    SystemJS y JSPM son omisiones muy notables. 8 de mayo de 2017 a las 5:10
  • 4
    Sí. El componente ahora está obsoleto github.com/componentjs/component 17/07/2017 a las 12:35
65

Vengo de un entorno Electron , donde necesito comunicación IPC entre un proceso de renderizado y el proceso principal. El proceso del renderizador se encuentra en un archivo HTML entre las etiquetas del script y genera el mismo error.

La línea

const {ipcRenderer} = require('electron')

arroja el error de referencia no detectado: require no está definido

Pude solucionarlo especificando la integración de Node.js como verdadera cuando la ventana del navegador (donde está incrustado este archivo HTML) se creó originalmente en el proceso principal.

function createAddItemWindow() {

    // Create a new window
    addItemWindown = new BrowserWindow({
        width: 300,
        height: 200,
        title: 'Add Item',

        // The lines below solved the issue
        webPreferences: {
            nodeIntegration: true
        }
})}

Eso me resolvió el problema. La solución se propuso aquí .

3
  • 1
    ¿Es esta solución segura? Escuché que no debería establecer nodeIntegration en verdadero, ¿es así? Soy un novato de Electron, así que esta es una pregunta genuina. 23 de marzo a las 23:46
  • Bueno, depende de cómo vaya a utilizar su aplicación electrónica. El hilo de comentarios de la pregunta original de StackOverflow a la que hice referencia brinda una breve descripción general de los aspectos de seguridad de hacer esto. Puedes seguir el hilo aquí . Pero en resumen: si esto se establece en verdadero, su aplicación tiene acceso al tiempo de ejecución del nodo, y si está ejecutando un código remoto potencialmente malicioso, es solo una receta para el desastre. 25 de marzo a las 6:22
  • This won't work if you don't use Electron. If you don't use Electron, the above code will fail with "Unexpected token '}'". 5 de mayo a las 5:23
49

ES6: en HTML, incluya el archivo JavaScript principal mediante el atributo type="module"( compatibilidad con el navegador ):

<script type="module" src="script.js"></script>

Y en el script.jsarchivo, incluya otro archivo como este:

import { hello } from './module.js';
...
// alert(hello());

Dentro del archivo incluido ( module.js), debes exportar la función / clase que importarás:

export function hello() {
    return "Hello World";
}

Un ejemplo práctico está aquí . Más información está aquí .

1
17

Reemplace todas las requiredeclaraciones con importdeclaraciones. Ejemplo:

// Before:
const Web3 = require('web3');

// After:
import Web3 from 'web3';

Funcionó para mí.

2
  • Como referencia, podría ser útil analizar esta pregunta sobre la diferencia entre los dos. 1 de agosto de 2020 a las 0:26
  • 1
    You might need to use type=module, which requires you to export the functions and variable names for them to work. 5 de mayo a las 5:24
3

Incluso usar esto no funcionará. Creo que la mejor solución es Browserify :

module.exports = {
  func1: function () {
   console.log("I am function 1");
  },
  func2: function () {
    console.log("I am function 2");
  }
};

-getFunc1.js-
var common = require('./common');
common.func1();
2

En mi caso utilicé otra solución.

Como el proyecto no requiere CommonJS y debe tener compatibilidad con ES3 (módulos no compatibles), todo lo que necesita es eliminar todas las declaraciones de exportación e importación de su código , porque su tsconfig no contiene

"module": "commonjs"

Pero use declaraciones de importación y exportación en sus archivos de referencia

import { Utils } from "./utils"
export interface Actions {}

El código final generado siempre tendrá (al menos para TypeScript 3.0) tales líneas

"use strict";
exports.__esModule = true;
var utils_1 = require("./utils");
....
utils_1.Utils.doSomething();
2
  • ¿De verdad te refieres a ES3? ES3 tiene 21 años, desde diciembre de 1999 . 29/12/20 a las 22:56
  • Algunos televisores inteligentes antiguos no son totalmente compatibles con es5. Entonces, solo es3 funciona en todas partes.
    ydanila
    29/12/20 a las 23:21
2
window = new BrowserWindow({
    webPreferences: {
        nodeIntegration: true,
        contextIsolation: false
    }
});
4
  • Bienvenido a Stack Overflow y gracias por tomarse el tiempo para crear una respuesta. Sin embargo, esta misma respuesta se ha dado en numerosas ocasiones como una solución a esta pregunta y, por lo tanto, no agrega ningún valor. Si pudiera desarrollar un poco ( editando esta publicación) sobre por qué y cómo funciona esta solución, esta respuesta podría convertirse en un buen consejo que es exactamente para lo que es este sitio. Además, esta es una respuesta puramente para el marco Electron, que el OP de la pregunta ni siquiera usa; considere publicar (una versión más elaborada) en un lugar más apropiado. 29 de marzo a las 12:57
  • considere actualizar con detalles sobre cómo esta respuesta es diferente de las otras respuestas; ¿Esta respuesta aborda un problema no abordado por otras respuestas? 29 de marzo a las 13:11
  • Esto no proporciona una respuesta a la pregunta. Una vez que tenga suficiente reputación , podrá comentar en cualquier publicación ; en su lugar, proporcione respuestas que no requieran aclaración por parte del autor de la pregunta . - De la revisión 30 de marzo a las 9:11
  • 1
    aunque no está claro pero de alguna manera se trabaja. 19 de mayo a las 14:50
1

Confirmo. Debemos agregar:

webPreferences: {
    nodeIntegration: true
}

Por ejemplo:

mainWindow = new BrowserWindow({webPreferences: {
    nodeIntegration: true
}});

Para mí, el problema se ha resuelto con eso.

1
1

Esto funcionó para mi

  1. Obtenga la última versión de la página de descarga de RequireJS.
    Es el archivo para RequestJS que es lo que usaremos.
  2. Cárguelo en su contenido HTML de esta manera: <script data-main="your-script.js" src="require.js"></script>

Notas!

Usar require(['moudle-name']) en your-script.js, norequire('moudle-name')

Usar const {ipcRenderer} = require(['electron']) , noconst {ipcRenderer} = require('electron')

2
  • 6
    Nunca, nunca recomiende un "clic aquí", nunca. En el mejor de los casos, es un RickRoll, pero no tenemos ni idea de lo que nos espera al final de ese enlace.
    ggdx
    26/10/19 a las 15:17
  • esto fue ayúdame !! pero ahora mi problema es que necesito cambiar manualmente el require ... eso es un problema, ¿sale algo en tsconfig que hace esto cuando compilo? 25 de marzo a las 12:14