Client auf Knoten: Nicht erfasster Referenzfehler: Erforderlich ist nicht definiert

320

Also schreibe ich eine Anwendung mit der Kombination aus Knoten / Express + Jade.

Ich habe client.js, die auf den Client geladen ist. In dieser Datei habe ich Code, der Funktionen aus anderen JavaScript-Dateien aufruft. Mein Versuch war zu verwenden

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

um den Inhalt von messages.js(genau wie ich es auf der Serverseite tun) und später Funktionen aus dieser Datei aufzurufen. Ist requirejedoch nicht auf der Clientseite definiert und löst einen Fehler des Formulars aus Uncaught ReferenceError: require is not defined.

Diese anderen JS-Dateien werden ebenfalls zur Laufzeit auf dem Client geladen, da ich die Links in der Kopfzeile der Webseite platziere. Der Client kennt also alle Funktionen, die aus diesen anderen Dateien exportiert werden.

Wie rufe ich diese Funktionen aus diesen anderen JS-Dateien (z. B. messages.js) in der Hauptdatei auf client.js, die den Socket für den Server öffnet?

MightyMouse
quelle
4
Warum <script src="messages.js"></script>rufst du sie nicht einfach an und rufst sie danach an?
Sterling Archer
1
Vielleicht kann dies eine Lösung sein, aber es gibt noch eine andere Sache, die mich betrifft. Ich habe auch eine Datei namens "Representation.js", um die Darstellung zu abstrahieren, die dem Client und dem Server gemeinsam ist. In dieser Datei habe ich auch erforderliche Anweisungen und auf der Serverseite sollte es in Ordnung sein, weil ich Node ausführe. Auf der Client-Seite wird dies jedoch ein Problem sein. Was denken Sie?
MightyMouse
2
Für Neulinge wie mich (die vor einer Woche noch nicht einmal "npm" buchstabieren konnten! :-) kann es hilfreich sein zu verstehen, dass die --requireOption von browserify require()auf der Client-Seite definiert wird. Siehe: lincolnloop.com/blog/speedy-browserifying-multiple-bundles
Hephaestus
2
@Sterling Archer ... Wenn es 100 solcher Dateien gibt ... können wir nicht weiter laden, in HTML richtig .........
Baradwaj Aryasomayajula

Antworten:

436

Dies liegt daran, require()dass das browser- / clientseitige JavaScript nicht vorhanden ist.

Jetzt müssen Sie einige Entscheidungen bezüglich Ihrer clientseitigen JavaScript-Skriptverwaltung treffen.

Sie haben drei Möglichkeiten:

  1. Verwenden <script>Tag.
  2. Verwenden Sie eine CommonJS- Implementierung. Synchrone Abhängigkeiten wie Node.js.
  3. Verwenden Sie eine AMD- Implementierung.

Zu den clientseitigen CommonJS -Implementierungen gehören:

(Die meisten von ihnen erfordern vor der Bereitstellung einen Erstellungsschritt.)

  1. Browserify - Sie können die meisten Node.js-Module im Browser verwenden. Das ist mein persönlicher Favorit.
  2. Webpack - Macht alles (bündelt JS, CSS usw.). Bekannt geworden durch die Welle von React.js. Bekannt für seine schwierige Lernkurve.
  3. Rollup - Neuer Anwärter. Nutzt ES6-Module. Beinhaltet Baumschüttelfähigkeiten (entfernt nicht verwendeten Code).

Sie können mehr über meinen Vergleich von Browserify mit (veralteter) Komponente lesen .

AMD- Implementierungen umfassen:

  1. RequireJS - Sehr beliebt bei clientseitigen JavaScript-Entwicklern. Nicht mein Geschmack wegen seiner asynchronen Natur.

Beachten Sie, dass Sie bei Ihrer Suche nach der richtigen Option etwas über Bower lesen werden . Bower ist nur für Paketabhängigkeiten gedacht und nicht für Moduldefinitionen wie CommonJS und AMD geeignet.

Hoffe das hilft einigen.

JP Richardson
quelle
1
Vielen Dank. Ich habe einen Minitest separat durchgeführt. Deshalb habe ich eine Weile gebraucht, um zu antworten. Ich werde vielleicht in ein paar Minuten mit einigen Fragen zurückkommen, um sicherzugehen, dass ich verstehe, wie diese Magie funktioniert. Ich möchte einfach alles zusammenfügen. Danke noch einmal. Browserify scheint zu rocken! :)
MightyMouse
6
Ich denke, JSPM sollte der Liste hinzugefügt werden.
Martijn
19
Könnte ich ein Beispiel für die Verwendung des <script>Tags zum Importieren einer React-Klasse ohne Verwendung eines nodeJs-Paketmanagers erhalten?
Louie Bertoncin
2
SystemJS und JSPM sind sehr bemerkenswerte Auslassungen.
Aluan Haddad
4
Ja. Komponente ist jetzt veraltet github.com/componentjs/component
i_emmanuel
42

Ich komme aus einer Elektronenumgebung, in der ich IPC-Kommunikation zwischen einem Renderer-Prozess und dem Hauptprozess benötige. Der Renderer-Prozess befindet sich in einer HTML-Datei zwischen Skript-Tags und generiert denselben Fehler. Die Linie

const {ipcRenderer} = require('electron')

löst den Uncaught ReferenceError aus: require ist nicht definiert

Ich konnte dies umgehen, indem ich die Knotenintegration als true angab, als das Browserfenster (in das diese HTML-Datei eingebettet ist) ursprünglich im Hauptprozess erstellt wurde.

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

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

Das hat das Problem für mich gelöst. Die Lösung wurde hier vorgeschlagen . Hoffe das hilft jemand anderem. Prost.

Kibonge Murphy
quelle
Vielen Dank. Ich denke, ich komme aus dem gleichen Shopping List App Video von YouTube hahaha
Luiscri
Genial - schön, solche Antworten zu finden, anstatt sich auf Vorspeisen zu verlassen, um alles auf magische Weise für Sie zusammenzustellen.
GhostBytes
Hervorragende Antwort für Electron-Benutzer!
Thoni56
tolle. funktioniert ziemlich gut für mich. Außerdem komme ich von Shopping List App Video zu o /
adahox_
24

ES6: In HTML enthalten Sie die Haupt-JS-Datei mit dem Attribut type="module"( Browser-Unterstützung ):

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

Und in der script.jsDatei enthalten Sie eine andere Datei wie diese:

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

In der enthaltenen Datei ( module.js) müssen Sie die Funktion / Klasse exportieren , die Sie importieren möchten

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

Arbeitsbeispiel hier .

Kamil Kiełczewski
quelle
1
@Curse Hier steht stackoverflow.com/a/44591205/860099 geschrieben "Modul erstellt einen Bereich, um Namenskollisionen zu vermeiden." Sie können "manuell" valzum Fensterobjekt setzen window.val = val. Hier ist Plunker: Plunker: plnkr.co/edit/aDyjyMxO1PdNaFh7ctBT?p=preview - diese Lösung funktioniert
Kamil Kiełczewski
1

In meinem Fall habe ich eine andere Lösung verwendet.

Da das Projekt keine CommonJs erfordert und ES3-kompatibel sein muss (Module werden nicht unterstützt), müssen Sie lediglich alle Export- und Importanweisungen aus Ihrem Code entfernen , da Ihre tsconfig keine enthält

"module": "commonjs"

Verwenden Sie jedoch Import- und Exportanweisungen in Ihren referenzierten Dateien

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

Der endgültig generierte Code enthält immer (zumindest für Typoskript 3.0) solche Zeilen

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

Selbst wenn dies nicht funktioniert, ist browserify meiner Meinung nach die beste Lösung:

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
quelle
0

Das hat bei mir funktioniert

  1. Speichern Sie diese Datei https://requirejs.org/docs/release/2.3.5/minified/require.js
  2. Laden Sie wie folgt in Ihren HTML-
    <script data-main="your-Scrpt.js" src="require.js"></script>
    Code!
    Verwenden Sie: -> require (['moudle-name']) in "your-script.js"
    nicht erforderlich ('Moudle-Name')
    const {ipcRenderer} = erfordern (['Elektron'])
    Nicht: const {ipcRenderer} = erfordern ('Elektron')
eaithy
quelle
2
Empfehlen Sie niemals einen "hier klicken". Bester Fall, es ist ein RickRoll, aber wir haben keine Ahnung, was uns am Ende dieses Links erwartet.
ggdx