Node.js - SyntaxError: Unerwarteter Tokenimport

442

Ich verstehe nicht, was los ist. Knoten v5.6.0 NPM v3.10.6

Der Code:

function (exports, require, module, __filename, __dirname) {
    import express from 'express'
};

Der Fehler:

SyntaxError: Unexpected token import
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:140:18)
    at node.js:1001:3
SofDroid
quelle
4
Verwenden Sie einen Transpiler wie Babel, um den Import in Nodejs zu verwenden, da er in Nodejs nicht nativ unterstützt wird. Es ist die beste Alternative für den Import erforderlich.
BHUVNESH KUMAR

Antworten:

483

Update 3: Seit Knoten 13 können Sie entweder die Erweiterung .mjs verwenden oder "type": "module" in Ihrer package.json festlegen. Sie müssen die --experimental-modulesFlagge nicht verwenden.

Update 2: Seit Knoten 12 können Sie entweder die .mjsErweiterung verwenden oder "type": "module"in Ihrer package.json festlegen. Und Sie müssen den Knoten mit dem --experimental-modulesFlag ausführen .

Update: In Knoten 9 wird es hinter einem Flag aktiviert und verwendet die .mjsErweiterung.

node --experimental-modules my-app.mjs

Obwohl importes in der Tat Teil von ES6 ist, wird es in NodeJS leider noch nicht standardmäßig unterstützt und hat erst vor kurzem Unterstützung in Browsern erhalten.

Siehe Browserkompatibilitätstabelle zu MDN und diesem Knotenproblem .

Aus James M Snells Update zu ES6-Modulen in Node.js (Februar 2017):

Die Arbeiten sind im Gange, aber es wird einige Zeit dauern - wir sehen derzeit mindestens ein Jahr.

Bis die Unterstützung nativ angezeigt wird, müssen Sie weiterhin klassische requireAnweisungen verwenden:

const express = require("express");

Wenn Sie wirklich neue ES6 / 7-Funktionen in NodeJS verwenden möchten, können Sie diese mit Babel kompilieren. Hier ist ein Beispielserver .

Scimonster
quelle
2
Weiß jemand, ob Knoten 10 mit standardmäßig aktivierter Unterstützung ausgeliefert wird? (voraussichtlich nächsten Monat)
Hartmut
2
@Scimonster ...... node --experimental-modules my-app.mjs (node: 12176) ExperimentalWarning: Der ESM-Modullader ist experimentell. {Fehler: Modul /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs kann bei der Suche nicht gefunden werden (intern / modules / esm / DefaultResolve.js: 23: 12) test-project / src / my-app.mjs bei der Suche (intern / modules / esm / DefaultResolve.js: 23: 12) .... eine Warnung auslösen konnte my-app.js nicht finden .... bitte vorschlagen .... i installierter Knoten Version 9.11.1
Leo

51
frustrierend, weil die meisten Tutorials da draußen von der Verwendung von Import sprechen, aber es gibt fast keine Unterstützung dafür. (Ich möchte 2 Stunden meines Lebens zurück lol)
Kiwicomb123

9
@ChaimEliyah: habe das gleiche Problem in Knoten v11.0.0
whoami


60

Leider unterstützt Node.js ES6 noch importnicht.

Um das zu erreichen, was Sie versuchen (das Express-Modul importieren), sollte dieser Code ausreichen

var express = require("express");

Stellen Sie außerdem sicher, dass Express durch Ausführen installiert ist

$ npm install express

Weitere Informationen zum Erlernen von Node.js finden Sie in den Node.js- Dokumenten.


8
importist nicht unbedingt eine Funktion von TypeScript. TypeScript ist ES6 mit Typisierungen. Sachen wie Import sind also ES6-native.
Borislemke

@borislemke Stimmt, ich habe das OP ein bisschen falsch interpretiert. :) Ich werde es ändern.
Baranskistad

Hallo, ich habe Express installiert, aber im Skript der Datei package.json, was sollen wir schreiben? Wenn ich "scripts" schreibe: {"start": "node index.js"}, sollte derselbe Fehler angezeigt werden. Bitte hilf mir.
Ravi Shah
node index.jsfunktioniert für mich, aber wenn ich renne node dist/main.jsbekomme ich auch Unexpected token import.
TheFox
@TheFox Sie haben wahrscheinlich einen Import in diese Datei. Nur weil du index.jsvorbei bist, heißt das nicht, dass auch dein dist/main.jsWille vorbei ist.
Baranskistad
34

Wie in anderen Antworten erwähnt, unterstützt Node JS derzeit keine ES6-Importe.

(Lesen Sie ab sofort EDIT 2)

Das Aktivieren von ES6-Importen in Knoten js bietet eine Lösung für dieses Problem. Ich habe es versucht und es hat bei mir funktioniert.

Führen Sie den folgenden Befehl aus:

    npm install babel-register babel-preset-env --save-dev

Jetzt müssen Sie eine neue Datei (config.js) erstellen und den folgenden Code hinzufügen.

    require('babel-register')({
        presets: [ 'env' ]
    })
    // Import the rest of our application.
    module.exports = require('./your_server_file.js')

Jetzt können Sie Importanweisungen schreiben, ohne Fehler zu erhalten.

Hoffe das hilft.

BEARBEITEN:

Sie müssen die neue Datei ausführen, die Sie mit dem obigen Code erstellt haben. In meinem Fall war es config.js. Also muss ich rennen:

    node config.js

EDIT 2:

Während des Experimentierens fand ich eine einfache Lösung für dieses Problem.

Erstellen Sie eine .babelrcDatei im Stammverzeichnis Ihres Projekts.

Fügen Sie Folgendes hinzu (und alle anderen benötigten Babel-Voreinstellungen können in dieser Datei hinzugefügt werden):

    {
        "presets": ["env"]
    }

Installieren Sie babel-preset-envmit dem Befehl npm install babel-preset-env --saveund installieren Sie dann babel-climit dem Befehlnpm install babel-cli -g --save

Wechseln Sie nun zu dem Ordner, in dem Ihre Server- oder Indexdatei vorhanden ist, und führen Sie Folgendes aus: babel-node fileName.js

Oder Sie können mit ausführen, npm startindem Sie Ihrer package.jsonDatei folgenden Code hinzufügen :

    "scripts": {
        "start": "babel-node src/index.js"
    }
Neerali Acharya
quelle
Wie mache ich das mit Elektronen? Ich habe es so versucht: "start": "babel-node electron .", aber kein Glück
tpbafk
2
@tpbafk Ich habe nicht an Elektronen gearbeitet. Aber ich habe etwas Ähnliches gefunden wie Ihr Problem Javascript - Wie man npm start für die Elektronen-App mit 'babel-node --presets es2015, stage-3' einstellt . Hoffe es hilft
Neerali Acharya
33

Fehler: SyntaxError: Unerwarteter Token- Import oder SyntaxError: Unerwarteter Token- Export


Lösung: Ändern Sie alle Ihre Importe als Beispiel

const express               = require('express');
const webpack               = require('webpack');
const path                  = require('path');
const config                = require('../webpack.config.dev');
const open                  = require('open');

Und ändern Sie auch Ihre export default = foo;zumodule.exports = foo;

supritshah1289
quelle
1
Ich wünschte, Sie hätten den Export-Standardteil etwas näher erläutert. Ich habe Probleme mit diesem Teil. Der Import funktioniert gut mit Ihrer Antwort.
JoeGalind
Vor meiner Antwort steht eine Antwort, die eine Erklärung enthält. Zur Verdeutlichung unterstützt Node jedoch keine ES6-Syntax. Wenn Sie Importieren sagen ... verwenden Sie die ES6-Syntax
supritshah1289
21

Ich bin schockiert, esmwurde nicht erwähnt. Mit diesem kleinen, aber mächtigen Paket können Sie entweder importoder verwenden require.

Installieren Sie esm in Ihrem Projekt

$ npm install --save esm

Aktualisieren Sie Ihr Node Start Script, um esm zu verwenden

node -r esm app.js

esmfunktioniert einfach. Ich habe eine TONNE Zeit damit verschwendet .mjsund --experimental-modulesnur um herauszufinden, dass eine .mjsDatei keine Datei importieren kann, die requireoder verwendet module.exports. Dies war ein großes Problem, während esmSie es mischen und anpassen können und es nur herausfindet ... esmfunktioniert einfach.

thedanotto
quelle
17

Für den Fall, dass Sie "import" immer noch nicht verwenden können, habe ich es so gehandhabt: Übersetzen Sie es einfach in eine knotenfreundliche Anforderung. Beispiel:

import { parse } from 'node-html-parser';

Ist das gleiche wie:

const parse = require('node-html-parser').parse;
Alberto
quelle
4
nicht wahr, wenn Sie (wie es wahrscheinlich der Fall ist) das exportSchlüsselwort verwenden
Daniel Thompson
@DanielThompson Entschuldigung, wenn dies ein Missverständnis sein kann, ich gebe nur eine Problemumgehung für diesen Fall. Wenn Sie ohne das exportSchlüsselwort arbeiten, danke trotzdem für Ihren hilfreichen Hinweis!
Alberto
Ich arbeite für mich. Danke
Ali Azhar
11

Mit dem Vorschlag für Babel 7 können Sie Entwicklungsabhängigkeiten hinzufügen

npm i -D @babel/core @babel/preset-env @babel/register

und fügen Sie eine .babelrc im Stammverzeichnis hinzu

{
"presets": [
  [
    "@babel/preset-env",
    {
      "targets": {
        "node": "current"
     }
    }
  ]
 ]
}

und zur .js-Datei hinzufügen

require("@babel/register")

oder wenn Sie es in der CLI ausführen, können Sie den erforderlichen Hook als -r @ babel / register verwenden, z.

$node -r @babel/register executeMyFileWithESModules.js
Jason Ashley
quelle
1
Die Installation von @ babel / preset-env und das Hinzufügen zu .babelrc war der Trick. In meinem Fall ist kein @ babel / register Plugin erforderlich.
Marcos R
8

Wenn Sie 'babel' verwenden können, versuchen Sie, Build-Skripte in package.json (- presets = es2015) wie folgt hinzuzufügen. Der Importcode muss in es2015 vorkompiliert werden

"build": "babel server --out-dir build --presets=es2015 && webpack"
ASTOMUSIK
quelle
Aber wird mein Aufruf npm startzuerst den "Build" oder zuerst den "Start" ausführen? (Der Start ist derzeit definiert:"nodemon src/app.js --exec \"npm run lint && node\"",
Pashute
Wenn ich dieses Cmd ausführe, zeigt es, dass der Server nicht existiert. Fehler
kumaresan_sd
6

Ab Node.js v12 (und dies jetzt wahrscheinlich ziemlich stabil ist, aber immer noch mit „experimentell“), haben Sie eine Reihe von Optionen für die Verwendung von ESM ( E CMA S cript M odule) in Node.js (für Dateien, gibt es eine dritter Weg zum Auswerten von Strings), hier ist, was die Dokumentation sagt:

Das --experimental-modulesFlag kann verwendet werden, um die Unterstützung für ECMAScript-Module (ES-Module) zu aktivieren.

Nach der Aktivierung behandelt Node.js Folgendes als ES-Module, wenn es nodeals erste Eingabe übergeben wird oder wenn durch importAnweisungen im ES-Modulcode darauf verwiesen wird :

  • Dateien, die auf enden .mjs.

  • Dateien, die auf .jsDateien ohne Erweiterung enden , oder Dateien ohne Erweiterung, wenn die nächste übergeordnete package.jsonDatei ein Feld der obersten Ebene "type"mit dem Wert von enthält "module".

  • Strings übergeben als Argument an --evaloder --printoder zum Ausleiten nodeüber STDIN, mit der Flagge --input-type=module.

Node.js behandelt alle anderen Eingabeformen als CommonJS, z. B. .jsDateien, in denen die nächste übergeordnete package.jsonDatei kein "type" Feld der obersten Ebene enthält , oder Zeichenfolgeneingaben ohne das Flag --input-type. Dieses Verhalten dient der Wahrung der Abwärtskompatibilität. Da Node.js jetzt sowohl CommonJS- als auch ES-Module unterstützt, ist es am besten, wenn möglich explizit zu sein. Node.js behandelt Folgendes als CommonJS, wenn es nodeals erste Eingabe übergeben wird oder wenn durch importAnweisungen im ES-Modulcode darauf verwiesen wird :

  • Dateien, die auf enden .cjs.

  • Dateien, die auf .jsDateien ohne Erweiterung enden , oder Dateien ohne Erweiterung, wenn die nächste übergeordnete package.jsonDatei ein Feld der obersten Ebene "type"mit dem Wert von enthält "commonjs".

  • Strings übergeben als Argument an --evaloder --printoder zum Ausleiten nodeüber STDIN, mit der Flagge --input-type=commonjs.

TJ Crowder
quelle
3

Als ich mit Express angefangen habe, wollte ich immer eine Lösung, um stattdessen Import zu verwenden

const express = require("express");
// to 
import express from "express"

Viele Male gehen Sie durch diese Zeile: - Unfortunately, Node.js doesn't support ES6's import yet.

Um anderen zu helfen, erstelle ich hier zwei neue Lösungen

1) esm : -

Der genial einfache ECMAScript-Modullader ohne Babel und ohne Bundle. Lass es funktionieren

  yarn add esm / npm install esm

Erstellen Sie start.js oder verwenden Sie Ihren Namespace

 require = require("esm")(module/*, options*/)
 // Import the rest of our application.
 module.exports = require('./src/server.js')
 // where server.js is express server start file

Ändern Sie Ihren package.josnPasspfad vonstart.js

  "scripts": {
    "start": "node start.js",
    "start:dev": "nodemon start.js",
  },
  "dependencies": {
+    "esm": "^3.2.25",
  },
  "devDependencies": {
+   "nodemon": "^1.19.2"
  }

2) Babel js : -

Dies kann in zwei Teile geteilt werden

a) Lösung 1 dank timonweb.com

b) Lösung 2

Verwenden Sie Babel 6 (ältere Version von babel-preset-stage-3 ^ 6.0 ), um eine .babelrcDatei in Ihrem Stammordner zu erstellen

{
    "presets": ["env", "stage-3"]
}

Installieren Sie babel-preset-stage-3

yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev

Änderung in package.json

"scripts": {
+   "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+   "start": "npm run build && node ./build/index.js",
+   "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+   "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+    "babel-cli": "^6.26.0",
+    "babel-polyfill": "^6.26.0",
+    "babel-preset-env": "^1.7.0",
+    "babel-preset-stage-3": "^6.24.1",
+    "nodemon": "^1.19.4"
},

Starten Sie Ihren Server

yarn start / npm start

Oooh nein, wir schaffen ein neues Problem

regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined

Dieser Fehler tritt nur auf, wenn Sie async / await in Ihrem Code verwenden. Verwenden Sie dann Polyfill, das eine benutzerdefinierte Regenerator-Laufzeit und Core-Js enthält. hinzufügen aufindex.js

import "babel-polyfill"

Auf diese Weise können Sie async / await verwenden

benutze Babel 7

Müssen Sie alles in Ihrem Projekt auf den neuesten Stand bringen, beginnen Sie mit babel 7 .babelrc

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

Einige Änderungen in package.json

"scripts": {
+  "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+  "start": "npm run build && node ./build/index.js",
+  "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+  "clean": "rm -rf build && mkdir build",
    ....
}
"devDependencies": {
+   "@babel/cli": "^7.0.0",
+   "@babel/core": "^7.6.4",
+   "@babel/node": "^7.0.0",
+   "@babel/polyfill": "^7.0.0",
+   "@babel/preset-env": "^7.0.0",
+   "nodemon": "^1.19.4"
....
}

und import "@babel/polyfill"am Startpunkt verwenden

import "@babel/polyfill"
import express from 'express'
const app = express()

//GET request
app.get('/', async (req, res) {
  // await operation
  res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))

Denkst du warum? start:dev

Ernsthaft. Es ist eine gute Frage, wenn Sie neu sind. Jede Änderung, die Sie jedes Mal yarn start:devmit dem Startserver ausführen, wird dann als Entwicklungsserver verwendet. Jede Änderung startet den Server automatisch neu, um mehr über nodemon zu erfahren

Ashok
quelle
2

In meinem Fall kümmerte es sich um die .babelrcDatei und sollte ungefähr Folgendes enthalten:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
Ghita Tomoiaga
quelle