Cliente en el nodo: Error de referencia no capturado: el requisito no está definido

322

Entonces, estoy escribiendo una aplicación con el nodo / express + jade combo.

Tengo client.js, que 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 JS 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 JS (como messages.js) en el client.jsarchivo principal que abre el socket al servidor?

MightyMouse
fuente
44
¿Por qué no solo <script src="messages.js"></script>y los llamas después de eso?
Sterling Archer
1
Quizás esto pueda ser una solución, pero hay otra cosa que me preocupa. También tengo un archivo llamado "rendering.js" para abstraer la representación que es común al cliente y al servidor. En ese archivo también tengo declaraciones de requerimiento y en el lado del servidor debería estar bien porque estoy ejecutando el nodo. Sin embargo, en el lado del cliente, esto será un problema. ¿Qué piensas?
MightyMouse
2
Para los novatos como yo (¡que ni siquiera podían deletrear "npm" hace una semana! :-), puede ser útil comprender que la --requireopción de browserify hace require()que se defina en el lado del cliente. Ver: lincolnloop.com/blog/speedy-browserifying-multiple-bundles
Hephaestus el
2
@Sterling Archer ... Si hay 100 de esos archivos ... no podemos seguir cargando el, en HTML correcto .........
Baradwaj Aryasomayajula

Respuestas:

436

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

Ahora tendrá que tomar algunas decisiones sobre la gestión de secuencias de comandos JavaScript del lado del cliente.

Tienes tres opciones:

  1. Usar <script>etiqueta
  2. Use una implementación de CommonJS . Dependencias sincrónicas como Node.js
  3. Use una implementación de AMD .

Las implementaciones del lado del cliente CommonJS incluyen:

(la mayoría de ellos 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 : hace todo (paquetes JS, CSS, etc.). Hecho popular por el surgimiento de React.js. Conocido por su difícil curva de aprendizaje.
  3. Rollup - Nuevo contendiente. Aprovecha los módulos ES6. Incluye habilidades para sacudir árboles (elimina el código no utilizado).

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

Las implementaciones de AMD incluyen:

  1. RequireJS : muy popular entre los desarrolladores de JavaScript del lado del cliente. No es de mi gusto debido a 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 se opina en las definiciones de módulos como CommonJS y AMD.

Espero que esto ayude un poco.

JP Richardson
fuente
1
Muchas gracias. Hice una mini prueba por separado, es por eso que me tomó un tiempo responder. Puedo volver con algunas preguntas en unos minutos solo para asegurarme de que entiendo cómo funciona esta magia. Solo quiero poner todo junto. Gracias de nuevo. ¡Browserify parece rockear! :)
MightyMouse
66
Creo que JSPM debería agregarse a la lista.
Martijn
19
¿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?
Louie Bertoncin
2
SystemJS y JSPM son omisiones muy notables.
Aluan Haddad
44
Si. El componente ahora está en desuso github.com/componentjs/component
i_emmanuel
43

Vengo de un entorno de electrones, donde necesito comunicación IPC entre un proceso de renderizador y el proceso principal. El proceso de representación se encuentra en un archivo HTML entre las etiquetas de script y genera el mismo error. La línea

const {ipcRenderer} = require('electron')

arroja el Error de referencia no capturado: el requisito no está definido

Pude evitar eso al especificar la integración de nodos como verdadera cuando la ventana del navegador (donde está incrustado este archivo HTML) se creó originalmente en el proceso principal.

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

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

Eso resolvió el problema para mí. La solución fue propuesta aquí . Espera que esto ayude a alguien más. Salud.

Kibonge Murphy
fuente
Muchas gracias. Supongo que vengo del mismo video de la aplicación Lista de compras de YouTube jajaja
Luiscri
Brillante: es bueno encontrar respuestas como esta en lugar de confiar en los principiantes para armar todo mágicamente por ti.
GhostBytes
Excelente respuesta para usuarios de Electron!
thoni56
asombroso. Funciona bastante bien para mí. también, vengo del video de la aplicación Lista de compras también o /
adahox_
26

ES6: en html, incluya el archivo js principal usando el atributo type="module"( soporte de navegador )

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

Y en el script.jsarchivo incluye otro archivo como ese:

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

Dentro del archivo incluido ( module.js) debe exportar la función / clase que importará

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

Ejemplo de trabajo aquí .

Kamil Kiełczewski
fuente
1
@Curse Here stackoverflow.com/a/44591205/860099 está escrito "El módulo crea un ámbito para evitar colisiones de nombres". se puede poner "manualmente" valen un objeto de ventana window.val = val. Aquí está plunker: Plunker: plnkr.co/edit/aDyjyMxO1PdNaFh7ctBT?p=preview - esta solución funciona
Kamil Kiełczewski
1

En mi caso usé otra solución.

Como el proyecto no requiere CommonJs y debe tener compatibilidad con ES3 (no se admiten módulos), 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 referenciados

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

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

"use strict";
exports.__esModule = true;
var utils_1 = require("./utils");
....
utils_1.Utils.doSomething();
ydanila
fuente
1

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();
Wael Chorfan
fuente
0

Esto funcionó para mí

  1. guarde este archivo https://requirejs.org/docs/release/2.3.5/minified/require.js
  2. cargar en su HTML como esta
    <script data-main="your-Scrpt.js" src="require.js"></script>
    Nota!
    use: -> require (['moudle-name']) en "your-script.js"
    no requiere ('nombre-moudle')
    const {ipcRenderer} = require (['electron'])
    No: const {ipcRenderer} = require ('electron')
eaithy
fuente
3
Nunca, jamás, recomiende un "clic aquí". El mejor de los casos, es un RickRoll, pero no tenemos idea de lo que nos espera al final de ese enlace.
ggdx