Node.js - SyntaxError: Неожиданный импорт токена


444

Я не понимаю, что не так. Узел 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. Существует лучшая альтернатива импорта, так что используйте это.
БХУВНЕШ КУМАР

Ответы:


485

Обновление 3: начиная с узла 13 , вы можете использовать расширение .mjs или установить «type»: «module» в вашем package.json. Вам не нужно использовать --experimental-modulesфлаг.

Обновление 2: начиная с узла 12 , вы можете использовать либо .mjsрасширение, либо установить его "type": "module"в package.json. И вам нужно запустить узел с --experimental-modulesфлагом.

Обновление: в узле 9 он включен за флагом и использует .mjsрасширение.

node --experimental-modules my-app.mjs

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

Смотрите таблицу сравнения браузеров на MDN и эту проблему с узлом .

Из обновления Джеймса М. Снелла о модулях ES6 в Node.js (февраль 2017 г.):

Работа продолжается, но это займет некоторое время - в настоящее время мы рассматриваем как минимум год.

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

const express = require("express");

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


2
Кто-нибудь знает, будет ли поставляться узел 10 с поддержкой по умолчанию? (дебютирует в следующем месяце)
Хартмут

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

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 Правда, я немного неверно истолковал ОП. :) Я изменю это.
baranskistad

привет, я установил экспресс, но в скрипте файла package.json что мы должны написать? Если я пишу "scripts": {"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.

(На данный момент читайте РЕДАКТИРОВАТЬ 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

РЕДАКТИРОВАТЬ 2:

Экспериментируя, я нашел одно простое решение этой проблемы.

Создайте .babelrcфайл в корне вашего проекта.

Добавьте следующее (и любые другие предустановки Babel, которые вам нужны, можно добавить в этот файл):

    {
        "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 для электронного приложения с помощью «babel-node --presets es2015, stage-3» . Надеюсь, это поможет
Neerali Acharya

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

или если вы запустите его в cli, вы можете использовать крючок require как -r @ babel / register, ex.

$node -r @babel/register executeMyFileWithESModules.js

1
Установка @ babel / preset-env и добавление его в .babelrc сделали свое дело. Нет необходимости в @ babel / зарегистрировать плагин в моем случае.
Маркос Р

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-stage-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 / await в своем коде. Затем используйте polyfill, который включает пользовательскую среду выполнения регенератора и core-js. добавить сверхуindex.js

import "babel-polyfill"

Это позволяет вам использовать async / await

использовать Вавилон 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.