Uzyskiwanie nieoczekiwanego eksportu tokenu

221

Próbuję uruchomić kod ES6 w moim projekcie, ale pojawia się nieoczekiwany błąd eksportu tokena.

export class MyClass {
  constructor() {
    console.log("es6");
  }
}
Jason
źródło
5
nie ma wystarczających informacji o środowisku lub konfiguracji, aby zaoferować jakąkolwiek pomoc. Ten błąd sugeruje, że albo webpack, albo babel nie działają poprawnie, ponieważ exportjest dostępny tylko w ES6, a te moduły zapewniają obsługę ES6.
Claies,
24
Powinieneś użyć module.exports = MyClass, a nieexport class MyClass
onmyway133

Odpowiedzi:

249

Używasz składni modułu ES6.

Oznacza to, że twoje środowisko (np. Node.js) musi obsługiwać składnię modułu ES6.

NodeJS używa składni modułu CommonJS ( module.exports), a nie składni modułu ES6 ( exportsłowo kluczowe).

Rozwiązanie:

  • Użyj babelpakietu npm, aby przetransponować swój ES6 do commonjscelu

lub

  • Refaktoryzuj ze składnią CommonJS.

Przykłady składni CommonJS to (z flaviocopes.com/commonjs/ ):

  • exports.uppercase = str => str.toUpperCase()
  • exports.a = 1
Phil Ricketts
źródło
15
Kiedy nodejs będzie wspierać importnatywnie? Myślałem, że wersja 10.0.0 będzie go mieć, ale najwyraźniej nie.
chovy
4
Wsparcie eksperymentalne @chovy jest dostępne z flagą „--experimental-modules”. Pliki muszą mieć rozszerzenie .mjs
Giovanni P.
1
Ten błąd pojawia się w przeglądarce Chrome 66 z natywną obsługą modułów.
Tom Russell
BTW: zauważ, że chociaż moduły obsługujące węzeł 10 / węzeł 12 stoją za flagą, nie obsługują go w trybie REPL - jednak jest obsługiwane w trybie eval w węźle 12 .
jakub.g
2
Dla kogoś nadal nie jest jasne, co do składni CommonJs. sprawdź ten link, może trochę pomóc. flaviocopes.com/commonjs
LT
142

W przypadku pojawienia się tego błędu może to być również związane ze sposobem włączenia pliku javascript do strony HTML. Podczas ładowania modułów musisz jawnie zadeklarować te pliki jako takie. Oto przykład:

//module.js:
function foo(){
   return "foo";
}

var bar = "bar";

export { foo, bar };

Po dołączeniu takiego skryptu:

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

Otrzymasz błąd:

Uncaught SyntaxError: Nieoczekiwany eksport tokena

Musisz dołączyć plik z atrybutem typu ustawionym na „moduł”:

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

A potem będzie działać zgodnie z oczekiwaniami i możesz zaimportować moduł do innego modułu:

import { foo, bar } from  "./module.js";

console.log( foo() );
console.log( bar );
Więdnąć
źródło
37
w przeciwieństwie do odpowiedzi „najbardziej uprzywilejowanej”, to faktycznie rozwiązuje problem i wyjaśnia, dlaczego tak się dzieje, nie sugerując, że jedyną opcją jest wykorzystanie metody CommonJS, metody APM lub transpilacja naszego kodu ... Byłby to również wyjątek do standardu w3c, gdzie typeoczekuje się, że będzie to prawidłowy typ MIME (zwany także typem nośnika), więc było to nieoczekiwane odkrycie. Dzięki!
Shaun Wilson
4
To naprawia błąd, ale potem pojawia się „Nieoczekiwany token {” w wierszu instrukcji importu w Chrome 67 z wbudowanym skryptem, np. <script> import ... </script>
PandaWood
1
@PandaWood Musisz użyć <script type="module">import ...</script>podczas importowania z modułu. Testowałem to w najnowszej wersji Chromium.
Vladimir S.
To naprawiło mój problem :)
user3651476
Pure JS (ES6) wspiera import, a to wyjaśnia dokładnie, dlaczego to poznałem
Eric
16

Moje dwa centy

Eksport

ES6

myClass.js

export class MyClass1 {
}
export class MyClass2 {
}

other.js

import { MyClass1, MyClass2 } from './myClass';

Alternatywa CommonJS

myClass.js

class MyClass1 {
}
class MyClass2 {
}
module.exports = { MyClass1, MyClass2 }
// or
// exports = { MyClass1, MyClass2 };

other.js

const { MyClass1, MyClass2 } = require('./myClass');

Eksportuj domyślnie

ES6

myClass.js

export default class MyClass {
}

other.js

import MyClass from './myClass';

Alternatywa CommonJS

myClass.js

module.exports = class MyClass1 {
}

other.js

const MyClass = require('./myClass');

Mam nadzieję że to pomoże

Barnstokkr
źródło
W przykładzie domyślnego eksportu ES6 napisałeś „domyślny eksport”, ale powinien to być „domyślny eksport”.
IAM_AL_X
@IAM_AL_X Dzięki za złapanie :-)
Barnstokkr
10

Aby użyć ES6 dodaj babel-preset-env

i w .babelrc:

{
  "presets": ["@babel/preset-env"]
}

Odpowiedz zaktualizowano dzięki komentarzowi @ghanbari, aby zastosować babel 7.

Jalal
źródło
8
jego pytanie nie dotyczy wyjaśnienia babel. Dlaczego więc odpowiadać na coś niepotrzebnego, co może mylić inne?
Jalal
7
@monsto to pytanie zostało już oznaczone babelprzez autora. Chociaż odpowiedź Phila Rickettsa wyjaśnia problem, co jest dobre, ta odpowiedź jest bezpośrednim rozwiązaniem problemu autora.
boycy
„@ babel / preset-env”
ghanbari
6

W tej chwili nie ma potrzeby korzystania z Babel (JS stał się bardzo wydajny), gdy można po prostu użyć domyślnego eksportu modułu JavaScript. Sprawdź pełny samouczek

Message.js

module.exports = 'Hello world';

app.js

var msg = require('./Messages.js');

console.log(msg); // Hello World
Alvin Konda
źródło
2
Jak więc eksportowałbyś klasę?
Sherwin Ablaña Dapito,
1
Usuwam moją odpowiedź, ponieważ pytanie dotyczyło ES6, a nie CommonJS używanego przez NodeJS. Proszę sprawdzić powyżej, aby uzyskać odpowiedź.
Alvin Konda,
@ SherwinAblañaDapito module.exports = class MyClass {} działa
Marian Klühspies
3

Instaluje pakiety Babel @babel/corei @babel/presetktóry przekształci ES6 do commonjs cel jako js węzłów nie rozumie bezpośrednio cele ES6

npm install --save-dev @babel/core @babel/preset-env

Następnie musisz utworzyć jeden plik konfiguracyjny z nazwą .babelrcw katalogu głównym projektu i dodać tam ten kod

{ "presets": ["@babel/preset-env"] }

YouBee
źródło
Musiałem także zainstalować @ babel / register, w przeciwnym razie nadal dostałbym komunikat „Składnia Błąd: nie można użyć instrukcji importu poza modułem”
cząsteczkowy
3

Naprawiłem to, tworząc plik punktu wejścia, taki jak.

// index.js
require = require('esm')(module)
module.exports = require('./app.js')

i każdy plik, który zaimportowałem do środka app.jsi poza nim, działał imports/exports teraz tak, jakbyś go uruchomiłnode index.js

Uwaga: jeśli app.jsużywa export default, staje się to require('./app.js').defaultpodczas korzystania z pliku punktu wejścia.

Alex Cory
źródło
1
Najlepsza odpowiedź na proste projekty niewymagające babel, webpack, paczki itp. Użyłem w projekcie monorepo z prostym / server express do projektu.
Działa
-3

Korzystanie ze składni ES6 nie działa w węźle, niestety trzeba mieć babel, aby kompilator zrozumiał składnię, taką jak eksport lub import.

npm install babel-cli --save

Teraz musimy utworzyć plik .babelrc, w pliku babelrc ustawimy babel na użycie ustawienia wstępnego es2015, które zainstalowaliśmy jako jego ustawienie wstępne podczas kompilacji do ES5.

W katalogu głównym naszej aplikacji utworzymy plik .babelrc. Npm instaluj babel-preset-es2015 - zapisz

W katalogu głównym naszej aplikacji utworzymy plik .babelrc.

{  "presets": ["es2015"] }

Mam nadzieję, że to działa ... :)

purushottam banerjee
źródło