Node.js - SyntaxError: Несподіваний імпорт маркера


443

Я не розумію, що не так. Вузол v5.6.0 NPM v3.10.6

Код:

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

Помилка:

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

4
Використовуйте транспілер, як Babel, щоб використовувати імпорт у Nodejs, оскільки він не підтримується в nodejs.Найкращою альтернативою імпорту є вимагати, так що йдіть з цим.
БХУВНЕШ КУМАР

Відповіді:


484

Оновлення 3: Починаючи з вузла 13 , ви можете використовувати або розширення .mjs, або встановити "type": "module" у своєму пакет.json. Вам не потрібно використовувати --experimental-modulesпрапор.

Оновлення 2: Починаючи з Вузла 12 , ви можете використовувати або .mjsрозширення, або встановити "type": "module"в пакеті.json. І вам потрібно запустити вузол із --experimental-modulesпрапором.

Оновлення: у Вузлі 9 він включений за прапором і використовує .mjsрозширення.

node --experimental-modules my-app.mjs

Хоча importвін дійсно є частиною ES6, він, на жаль, ще не підтримується в NodeJS за замовчуванням, і лише недавно отримав підтримку в браузерах.

Дивіться таблицю компакт-переглядачів на MDN та цю проблему з вузлом .

З оновлення James M Snell щодо модулів ES6 в Node.js (лютий 2017 р.):

Робота триває, але це займе певний час - Зараз ми переглядаємо щонайменше рік.

Поки підтримка не з’явиться на самому світі, вам доведеться продовжувати використовувати класичні requireзаяви:

const express = require("express");

Якщо ви дійсно хочете використовувати нові функції ES6 / 7 в NodeJS, можете скласти це за допомогою Babel. Ось прикладний сервер .


2
хтось знає, чи буде вузол 10 поставлятись із підтримкою, включеною за замовчуванням? (належить до дебюту наступного місяця)
Хартмут

2
@Scimonster ...... node --experimental-module my-app.mjs (вузол: 12176) ExperimentalWarning: Завантажувач модулів ESM експериментальний. {Помилка: Неможливо знайти модуль /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs при пошуку (внутрішній / модулі / esm / DefaultResolve.js: 23: 12) тест-проект / src / my-app.mjs при пошуку (внутрішній / модулі / esm / DefaultResolve.js: 23: 12) .... кидаючи попередження, не вдалося знайти my-app.js .... будь ласка, підкажіть .... я встановлено вузол версії 9.11.1
Leo

52
засмучує, оскільки більшість навчальних посібників там говорять про використання імпорту, але майже немає підтримки для цього. (Я хочу 2 години свого життя назад
хаха

9
@ChaimEliyah: отримала таку ж проблему у вузлі v11.0.0
whoami

5
Ще потрібен прапор у v12 nodejs.org/api/esm.html#esm_ecmascript_modules
ABabin

60

На жаль, Node.js ще не підтримує ES6 import.

Щоб виконати те, що ви намагаєтеся (імпортувати модуль Express), цього коду має бути достатньо

var express = require("express");

Також переконайтеся, що у вас встановлений Express, запущений

$ npm install express

Дивіться Документи Node.js для отримання додаткової інформації про вивчення Node.js.


8
importне обов'язково є функцією TypeScript. TypeScript - це ES6 з типізацією. Тож такі речі, як імпорт, - це ES6.
borislemke

@borislemke Щоправда, я трактував ОП трохи неправильно. :) Я його зміню.
baranskistad

привіт, я встановив експрес, але в скрипті файлу package.json що нам писати? Якщо я пишу "скрипти": {"start": "node index.js"}, то він повинен відображати таку ж помилку. будь ласка, допоможи мені.
Раві Шах

node index.jsпрацює для мене, але коли я бігаю, node dist/main.jsя також отримую Unexpected token import.
TheFox

@TheFox ви, мабуть, імпортуєте у цей файл. Тільки тому, що ваше index.jsпроходить не означає, що і ваш dist/main.jsпройде.
баранскістад

34

Як було сказано в інших відповідях, Node JS в даний час не підтримує імпорт ES6.

(Відтепер читайте EDIT 2)

Увімкнути імпорт ES6 у вузлі js дозволяє вирішити цю проблему. Я спробував це, і це спрацювало на мене.

Виконайте команду:

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

Тепер потрібно створити новий файл (config.js) і додати до нього наступний код.

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

Тепер ви можете писати заяви про імпорт, не отримуючи помилок.

Сподіваюсь, це допомагає.

Редагувати:

Вам потрібно запустити новий файл, який ви створили з вищевказаним кодом. У моєму випадку це було config.js. Тому я повинен бігти:

    node config.js

EDIT 2:

Експериментуючи, я знайшов одне просте рішення цього питання.

Створіть .babelrcфайл у корені вашого проекту.

Додайте наступне (і будь-які інші необхідні пресети, які вам потрібні, можна додати у цей файл):

    {
        "presets": ["env"]
    }

Встановити babel-preset-envза допомогою команди npm install babel-preset-env --save, а потім встановити babel-cliза допомогою командиnpm install babel-cli -g --save

Тепер перейдіть до папки, де існує ваш сервер чи індексний файл, і запустіть за допомогою: babel-node fileName.js

Або ви можете запустити npm start, додавши у package.jsonфайл наступний код :

    "scripts": {
        "start": "babel-node src/index.js"
    }

Як це зробити з електроном? Я намагався так: "start": "babel-node electron .", але не пощастило
tpbafk

2
@tpbafk Я не працював над електроном. Але я знайшов щось подібне до вашої проблеми javascript - Як встановити npm start для електронної програми за допомогою «babel-node --presets es2015, stage-3» . Сподіваюся, що це допомагає
Неералі Ачарія

33

Помилка: SyntaxError: Несподіваний імпорт маркера або SyntaxError: Несподіваний експорт маркера


Рішення. Змініть увесь імпорт як приклад

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

А також змінити export default = foo;наmodule.exports = foo;


1
Я хотів би, щоб ви пояснили детальніше частину експорту за замовчуванням. У мене проблеми з цією частиною. Імпорт чудово працює з вашою відповіддю.
JoeGalind

Перед моєю відповіддю є відповідь, яка має пояснення. Але для уточнення Node не підтримує синтаксис ES6. Коли ви говорите «Імпорт», ви використовуєте синтаксис
ES6

22

Я в шоці esmне згадувався. Цей невеликий, але могутній пакет дозволяє вам використовувати importабо require.

Встановіть esm у свій проект

$ npm install --save esm

Оновіть сценарій запуску вузла, щоб використовувати ESM

node -r esm app.js

esmпросто працює. Я витрачав ТОН часу, .mjsі --experimental-modulesлише щоб дізнатися .mjsфайл, не можна імпортувати файл, який використовує requireабо module.exports. Це було величезною проблемою, тоді як esmви можете змішувати і поєднувати, і це просто з'ясовується ... esmпросто працює.


17

Якщо ви все ще не можете використовувати "імпорт", ось як я обробляв це: Просто переведіть його на потрібний вузол. Приклад:

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

Це те саме, що:

const parse = require('node-html-parser').parse;

4
не вірно, якщо ви (як це, мабуть, так) використовуєте exportключове слово
Даніель Томпсон,

@DanielThompson Вибачте, якщо це може бути непорозумінням, я просто даю вирішення цього випадку, якщо ви працюєте без exportключового слова, все-таки дякую за вашу корисну записку!
Альберто

Працює для мене. Спасибі
Алі Ашар

11

Babel 7 пропозиція Ви можете додати залежність від розробників

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

і додайте .babelrc в корінь

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

і додати у .js файл

require("@babel/register")

або якщо запустити його в кліпі, ви можете використовувати гачок вимагати як -r @ babel / register, напр.

$node -r @babel/register executeMyFileWithESModules.js

1
Встановлення @ babel / preset-env та додавання його до .babelrc зробило трюк. У моєму випадку немає потреби в плагіні @ babel / register.
Маркос Р

8

якщо ви можете використовувати "babel", спробуйте додати сценарії збірки в package.json (- presets = es2015), як показано нижче. це зробити для попереднього компіляції коду імпорту до es2015

"build": "babel server --out-dir build --presets=es2015 && webpack"

але чи буде мій заклик npm startспочатку зробити "побудову" чи спочатку зробити "старт"? (Старт зараз визначений:"nodemon src/app.js --exec \"npm run lint && node\"",
pashute

якщо я запускаю цей cmd, він показує, що сервер не існує помилки
kumaresan_sd

6

Що стосується Node.js v12 (і це, мабуть, зараз досить стабільно, але все ще позначено "експериментальним"), у вас є пара варіантів використання ESM ( E CMA S cript M odules) у Node.js (для файлів є третій спосіб для обведення рядків), ось що говорить документація :

--experimental-modulesПрапор може бути використаний для включення підтримки модулів ECMAScript (ES модулів).

Після ввімкнення Node.js буде розглядати наступні як модулі ES при передачі в nodeякості початкового вводу або на посилання на них importу заявці в коді модуля ES:

  • Файли, що закінчуються на .mjs.

  • Файли, що закінчуються у .jsфайлах або без розширень, коли найближчий батьківський package.jsonфайл містить поле верхнього рівня "type"зі значенням "module".

  • Рядки передаються як аргумент --evalабо --print, або конвеєра з nodeдопомогою STDIN, з прапором --input-type=module.

Node.js буде розглядати як CommonJS всі інші форми введення, такі як .jsфайли, де найближчий батьківський package.jsonфайл не містить "type" поля верхнього рівня , або рядкове введення без прапора --input-type. Така поведінка полягає у збереженні відсталої сумісності. Однак тепер, коли Node.js підтримує і модулі CommonJS, і ES, краще бути явним, коли це можливо. Node.js буде розглядати наступне як CommonJS, коли його передають nodeяк початковий вхід, або коли на нього посилаються importзаяви у коді модуля ES:

  • Файли, що закінчуються на .cjs.

  • Файли, що закінчуються у .jsфайлах або без розширень, коли найближчий батьківський package.jsonфайл містить поле верхнього рівня "type"зі значенням "commonjs".

  • Рядки передаються як аргумент --evalабо --print, або конвеєра з nodeдопомогою STDIN, з прапором --input-type=commonjs.


3

Коли я почав працювати з express, завжди хотів, щоб рішення використовувати імпорт, а не вимагати

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

Багато часу проходимо через цю лінію: - Unfortunately, Node.js doesn't support ES6's import yet.

Тепер, щоб допомогти іншим, я створив тут два нових рішення

1) esm : -

Навантажувач модулів ECMAScript без наборів, без упаковки. давайте змусимо це працювати

  yarn add esm / npm install esm

створити start.js або використовувати простір імен

 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

Змініть свій package.josnшлях пропускуstart.js

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

2) Babel js : -

Це можна розділити на 2 частини

а) Рішення 1 завдяки timonweb.com

б) Рішення 2

використовувати Babel 6 (старіша версія babel-preset-stage-3 ^ 6.0 ) створити .babelrcфайл у вашій кореневій папці

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

Встановіть babel-preset-етап-3

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

Зміна в 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"
},

Запустіть ваш сервер

yarn start / npm start

О, ні, ми створюємо нову проблему

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

Ця помилка виникає лише тоді, коли ви використовуєте async / очікуєте у своєму коді. Потім використовуйте polyfill, який включає користувальницьку програму регенератора та core-js. додати поверхindex.js

import "babel-polyfill"

Це дозволяє використовувати async / wait

використовувати Babel 7

Потрібно оновити кожну річ у вашому проекті, нехай почнемо з babel 7 .babelrc

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

Деякі зміни в 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"
....
}

і використовувати import "@babel/polyfill"на стартовій точці

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

Ви думаєте, чому start:dev

Серйозно. Добре питання, якщо ви новачок. Кожна зміна, яку ви запускаєте із запуску сервера кожного разу, потім використовуйте yarn start:devяк сервер розвитку, кожну зміну перезавантажте сервер автоматично для отримання додаткової інформації про nodemon


2

У моєму випадку він доглядав .babelrcфайл, і він повинен містити щось подібне:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.