Klient w węźle: Uncaught ReferenceError: wymagany nie jest zdefiniowany

320

Piszę więc aplikację z kombinacją węzeł / express + jade.

Mam client.js, który jest ładowany na kliencie. W tym pliku mam kod wywołujący funkcje z innych plików JavaScript. Moja próba polegała na użyciu

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

w celu załadowania zawartości messages.js(tak jak robię po stronie serwera), a później funkcji wywoływania z tego pliku. Jednak requirenie jest zdefiniowany po stronie klienta i zgłasza błąd formularza Uncaught ReferenceError: require is not defined.

Te inne pliki JS są również ładowane w środowisku wykonawczym na kliencie, ponieważ umieszczam łącza w nagłówku strony. Dzięki temu klient zna wszystkie funkcje eksportowane z tych innych plików.

Jak wywołać te funkcje z tych innych plików JS (takich jak messages.js) w głównym client.jspliku, który otwiera gniazdo na serwerze?

MightyMouse
źródło
4
Dlaczego po prostu nie <script src="messages.js"></script>zadzwonisz po nich?
Sterling Archer
1
Być może może to być rozwiązanie, ale niepokoi mnie jeszcze jedna rzecz. Mam również plik o nazwie „Representation.js” do wyodrębnienia reprezentacji wspólnej dla klienta i serwera. W tym pliku mam także instrukcje i po stronie serwera powinno być w porządku, ponieważ działam jako węzeł. Jednak po stronie klienta będzie to problem. Co myślisz?
MightyMouse
2
Dla początkujących jak ja (którzy nie mogli nawet przeliterować „npm” tydzień temu! :-), pomocne może być zrozumienie, że --requireopcja Browserify powoduje, require()że jest definiowana po stronie klienta. Zobacz: lincolnloop.com/blog/speedy-browserifying-multiple-bundles
Hefajstos
2
@Sterling Archer ... Jeśli jest 100 takich plików ... nie możemy nadal ładować, w HTML, w prawo .........
Baradwaj Aryasomayajula

Odpowiedzi:

436

Wynika to z faktu, require()że nie istnieje on w przeglądarce JavaScript / po stronie klienta.

Teraz będziesz musiał dokonać pewnych wyborów dotyczących zarządzania skryptami JavaScript po stronie klienta.

Masz trzy opcje:

  1. Użyj <script>tagu.
  2. Użyj implementacji CommonJS . Zależności synchroniczne, takie jak Node.js
  3. Użyj implementacji AMD .

Implementacje po stronie klienta CommonJS obejmują:

(większość z nich wymaga etapu kompilacji przed wdrożeniem)

  1. Browserify - Możesz używać większości modułów Node.js w przeglądarce. To mój osobisty faworyt.
  2. Webpack - robi wszystko (zawiera JS, CSS itp.). Popularny dzięki fali React.js. Słynie z trudnej krzywej uczenia się.
  3. Rollup - Nowy pretendent. Wykorzystuje moduły ES6. Obejmuje zdolność do wstrząsania drzewem (usuwa nieużywany kod).

Możesz przeczytać więcej o moim porównaniu składnika Browserify vs (wycofany) .

Implementacje AMD obejmują:

  1. RequireJS - bardzo popularny wśród programistów JavaScript po stronie klienta. Nie mój gust z powodu jego asynchronicznej natury.

Uwaga: w trakcie wybierania odpowiedniego rozwiązania przeczytasz o Bower . Bower jest przeznaczony tylko dla zależności pakietów i nie jest uwzględniany w definicjach modułów, takich jak CommonJS i AMD.

Mam nadzieję, że to pomaga niektórym.

JP Richardson
źródło
1
Dziękuję Ci bardzo. Zrobiłem mini test osobno, dlatego zajęło mi trochę czasu, aby odpowiedzieć. Za kilka minut mogę wrócić z kilkoma pytaniami, aby upewnić się, że rozumiem, jak działa ta magia. Chcę tylko wszystko złożyć. Dzięki jeszcze raz. Browserify wydaje się kołysać! :)
MightyMouse
6
Myślę, że JSPM powinien zostać dodany do listy.
Martijn
19
Czy mogę uzyskać przykład użycia <script>znacznika do zaimportowania klasy React bez użycia menedżera pakietów nodeJs?
Louie Bertoncin,
2
SystemJS i JSPM to bardzo znaczące pominięcia.
Aluan Haddad
4
Tak. Składnik jest teraz przestarzały github.com/componentjs/component
i_emmanuel
43

Pochodzę ze środowiska elektronowego, w którym potrzebuję komunikacji IPC między procesem renderującym a procesem głównym. Proces renderowania znajduje się w pliku HTML między znacznikami skryptu i generuje ten sam błąd. Linia

const {ipcRenderer} = require('electron')

zgłasza Uncaught ReferenceError: wymagany nie jest zdefiniowany

Byłem w stanie obejść ten problem, określając integrację węzła jako prawdziwą, gdy okno przeglądarki (gdzie osadzony jest ten plik HTML) zostało pierwotnie utworzone w głównym procesie.

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

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

To rozwiązało problem dla mnie. Rozwiązanie zaproponowano tutaj . Ma nadzieję, że pomoże to komuś innemu. Twoje zdrowie.

Kibonge Murphy
źródło
Dziękuję Ci bardzo. Chyba pochodzę z tego samego filmu z aplikacji Shopping List z YouTube hahaha
Luiscri
Genialne - miło jest znaleźć takie odpowiedzi zamiast polegać na przystawkach, aby magicznie wszystko dla ciebie połączyć.
GhostBytes,
Doskonała odpowiedź dla użytkowników Electron!
thoni56
niesamowity. działa dla mnie całkiem dobrze.
Też
25

ES6: W html dołącz główny plik js przy użyciu atrybutu type="module"( obsługa przeglądarki ):

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

I w script.jspliku dołącz inny taki plik:

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

Wewnątrz dołączonego pliku ( module.js) musisz wyeksportować funkcję / klasę , którą zaimportujesz

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

Przykład roboczy tutaj .

Kamil Kiełczewski
źródło
1
@ Curse Tutaj stackoverflow.com/a/44591205/860099 jest napisane: „Moduł tworzy zakres, aby uniknąć kolizji nazw”. Możesz „ręcznie” umieścić valobiekt w oknie window.val = val. Oto plunker: Plunker: plnkr.co/edit/aDyjyMxO1PdNaFh7ctBT?p=preview - to rozwiązanie działa
Kamil Kiełczewski
1

W moim przypadku zastosowałem inne rozwiązanie.

Ponieważ projekt nie wymaga CommonJ i musi mieć kompatybilność z ES3 (moduły nieobsługiwane), wystarczy usunąć wszystkie instrukcje eksportu i importu z kodu , ponieważ tsconfig nie zawiera

"module": "commonjs"

Ale używaj instrukcji importu i eksportu w plikach, do których się odwołujesz

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

Ostatecznie wygenerowany kod będzie zawsze zawierał (przynajmniej dla maszynopisu 3.0) takie wiersze

"use strict";
exports.__esModule = true;
var utils_1 = require("./utils");
....
utils_1.Utils.doSomething();
ydanila
źródło
1

Nawet użycie tego nie zadziała, myślę, że najlepszym rozwiązaniem jest 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
źródło
0

To zadziałało dla mnie

  1. zapisz ten plik https://requirejs.org/docs/release/2.3.5/minified/require.js
  2. załaduj do swojego HTML tak jak ta
    <script data-main="your-Scrpt.js" src="require.js"></script>
    Uwaga!
    użyj: -> wymagają (['moudle-name']) w "your-script.js"
    nie wymagają („moudle-name”)
    const {ipcRenderer} = wymagają (['elektron'])
    Not: const {ipcRenderer} = wymagają ('elektron')
eaithy
źródło
3
Nigdy, nigdy nie polecam „kliknij tutaj”, nigdy. Najlepszy przypadek to RickRoll, ale nie mamy pojęcia, co nas czeka na końcu tego linku.
ggdx