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?


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.


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.


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 .


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

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

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')

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.