SyntaxError: Невозможно использовать оператор импорта вне модуля

53

У меня есть проект ApolloServer, который доставляет мне неприятности, поэтому я подумал, что могу обновить его и столкнулся с проблемами при использовании последней версии Babel. Мой "index.js" это:

require('dotenv').config()
import {startServer} from './server'
startServer()

И когда я запускаю его, я получаю сообщение об ошибке «SyntaxError: Невозможно использовать оператор импорта вне модуля». Сначала я попытался сделать что-то, чтобы убедить TPTB *, что это был модуль (но безуспешно). Поэтому я изменил «импорт» на «требовать», и это сработало.

Но теперь у меня есть около двух десятков «импортов» в других файлах, выдающих мне ту же ошибку.

* Я уверен, что корень моей проблемы в том, что я даже не уверен, что жалуется на проблему. Я вроде бы предположил, что это был Babel 7 (так как я пришел из Babel 6, и мне пришлось сменить пресеты), но я не уверен на 100%.

Большая часть того, что я нашел для решений, похоже, не относится к прямому Node. Как этот здесь:

Импорт модуля ES6, выдающий «Uncaught SyntaxError: Неожиданный идентификатор»

Говорит, что это было решено добавлением «type = module», но это обычно происходит в HTML, которого у меня нет. Я также попытался использовать старые пресеты моего проекта:

"presets": ["es2015", "stage-2"],
"plugins": []

Но это вызывает у меня еще одну ошибку: «Ошибка: файлы плагинов / пресетов не могут экспортировать объекты, только функции».

ОБНОВЛЕНИЕ: Вот зависимости, с которых я начал:

"dependencies": {
"@babel/polyfill": "^7.6.0",
"apollo-link-error": "^1.1.12",
"apollo-link-http": "^1.5.16",
"apollo-server": "^2.9.6",
"babel-preset-es2015": "^6.24.1",
user3810626
источник
1
Привет, с той же проблемой прямо сейчас. Не могли бы вы также поделиться своими зависимостями? Может быть, даже различия до и после вашего обновления. Я мог бы проверить мои, чтобы увидеть, можем ли мы найти похожие пакеты, которые могут вызвать проблемы.
рысь
Я просто заменил все «импорт» на «требует», и теперь все хорошо. Тупой, но это не стоило усилий, чтобы понять это прямо сейчас. Я буду обновлять оригинал с зависимостями, хотя. Если у вас есть какие-либо сведения, я проверю их на соответствие исходному коду.
user3810626
1
Синтаксис CommonJS (require и module.exports) был исходным форматом для узла, и webpack также поддерживает его, но синтаксис модуля ES6 (export, import) является более новым способом, и теперь его поддерживают узел и webpack. Я читал, что узел теперь поддерживает импорт, но так много уроков показывают, что для чистых узлов достаточно использовать этот синтаксис для узла.
Тед Фицпатрик
1
Наконец, для меня путь , казалось, это: github.com/vuejs/vue-jest/issues/134#issuecomment-461755061 Установка предустановленное в jest.config.jsк 'ts-jest/presets/js-with-ts'- до сих пор некоторые другие вопросы , но решить это один большой. ..... да, моя проблема была связана с тестированием ... нормальные сборки были в порядке
lynx
Рысь, Интересно. Сам не использую Jest. Тед, интересно. ОК, я не буду потеть
user3810626

Ответы:

52

Обновление 2020 (Узел 13.2.0+)

Убедитесь, что у вас установлена ​​последняя версия Node. Не --experimental-modulesфлаг больше не нужен. Просто выполните одно из следующих действий :

  • Добавьте "type": "module"к ближайшему родителю package.json. При этом все .jsи .mjsфайлы интерпретируются как модули ES. Вы можете интерпретировать отдельные файлы как CommonJS, используя .cjsрасширение.

ИЛИ

  • Явно назовите файлы с .mjsрасширением. Все остальные файлы, например, .jsбудут интерпретироваться как CommonJS, который используется по умолчанию, если typeон не определен в package.json.
jabacchetta
источник
Если я использую это, то измените путь, чтобы включить «js» для требуемого файла, затем измените формат операторов экспорта в требуемом файле, а затем возьмите все операторы «require», которые я изменил из «import» - потому что теперь «требуется» неизвестно - это сработает, поэтому я приму этот ответ.
user3810626
2
Это не совсем вариант, если проблема находится в node_modules / right? Есть идеи как исправить в таком случае?
Трент Бинг
18

Согласно официальному документу ( https://nodejs.org/api/esm.html#esm_code_import_code_statements ):

Операторы импорта разрешены только в модулях ES. Для аналогичной функциональности в CommonJS, см. Import ().

Чтобы Node рассматривал ваш файл как модуль ES, вам необходимо ( https://nodejs.org/api/esm.html#esm_enabling ):

  • добавить "type": "module" в package.json
  • добавить флаг "--experimental-modules" к вызову узла
shmekor
источник
6

У меня была та же проблема, и следующие исправили ее (используя узел 12.13.1):

  • Измените расширение файлов .js на .mjs
  • Добавьте флаг --experimental-modules при запуске приложения.
  • Необязательно: добавьте "type": "module" в ваш package.json

дополнительная информация: https://nodejs.org/api/esm.html

iseenoob
источник
-1

У меня была эта проблема в молодом проекте Express API.

Код сервера-нарушителя в src/server/server.js:

import express from 'express';
import {initialDonationItems, initialExpenditureItems} from "./DemoData";

const server = express();

server.get('/api/expenditures', (req, res) => {
  res.type('json');
  res.send(initialExpenditureItems);
});

server.get('/api/donations', (req, res) => {
  res.type('json');
  res.send(initialDonationItems);
});

server.listen(4242, () => console.log('Server is running...'));

Здесь были мои зависимости:

{
  "name": "contributor-api",
  "version": "0.0.1",
  "description": "A Node backend to provide storage services",
  "scripts": {
    "dev-server": "nodemon --exec babel-node src/server/server.js --ignore dist/",
    "test": "jest tests"
  },
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.9.6",
    "@babel/node": "^7.8.7",
    "babel-loader": "^8.1.0",
    "express": "^4.17.1",
    "mysql2": "^2.1.0",
    "sequelize": "^5.21.7",
    "sequelize-cli": "^5.5.1"
  },
  "devDependencies": {
    "jest": "^25.5.4",
    "nodemon": "^2.0.3"
  }
}

И вот бегун, который бросил ошибку:

nodemon --exec babel-node src/server/server.js --ignore dist

Это было неприятно, так как у меня был похожий проект Express, который работал нормально.

Первым решением было добавить эту зависимость:

npm install @babel/preset-env

А затем подключить его, используя babel.config.jsв корне проекта:

module.exports = {
  presets: ['@babel/preset-env'],
};

Я не совсем понимаю, почему это работает, но я скопировал это из авторитетного источника , поэтому я счастлив придерживаться этого.

halfer
источник
Да, моя проблема заключалась в том, что в коде было множество предустановок, и я никогда не мог найти правильный баланс между вещами, которые я хотел, и вещами, которые я не хотел / которые ломали вещи.
user3810626
Я весь день переживал сбивающие с толку сбои JS @ user3810626 - я подозреваю, что моя проблема в том, что я довольно плохо знаком с языком и экосистемой, и сейчас мне нужно отложить некоторое обучение, чтобы все заработало. Как там ...:-)
halfer
1
Удачи! Это джунгли там! (Я имею в виду, буквально, экосистема JS - это джунгли ...)
user3810626
-2
  1. У меня была та же проблема, когда я начал использовать babel ... Но позже у меня было решение ... У меня больше не было проблемы ... В настоящее время, Node v12.14.1, "@ babel / node" : "^ 7.8.4", я использую babel-node и nodemon для выполнения (также хорошо работает узел ..)
  2. package.json: "start": "nodemon --exec babel-node server.js" debug ":" babel-node debug server.js "!! note: server.js - это мой входной файл, вы можете использовать свой.
  3. launch.json При отладке вам также необходимо настроить файл launch.json "runtimeExecutable": "$ {workspaceRoot} /node_modules/.bin/babel-node" !! note: плюс runtimeExecutable в конфигурацию.
  4. Конечно, с babel-node вам также обычно нужно отредактировать другой файл, такой как файл babel.config.js / .babelrc.
MrLetmein
источник
-2

Мое решение состояло в том, чтобы включить путь babel-node при запуске nodemon следующим образом:

nodemon node_modules/.bin/babel-node index.js

Вы можете добавить в свой скрипт package.json как:

debug: nodemon node_modules/.bin/babel-node index.js

ПРИМЕЧАНИЕ. Мой входной файл - index.js, замените его вашим входным файлом (у многих есть app.js / server.js).

ишаб ачарья
источник