Błąd składni: nie można użyć instrukcji importu poza modułem

52

Mam projekt ApolloServer, który sprawia mi problemy, więc pomyślałem, że mogę go zaktualizować i napotkałem problemy podczas korzystania z najnowszej wersji Babel. Mój „index.js” to:

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

Po uruchomieniu pojawia się błąd „Błąd składni: nie można użyć instrukcji importu poza modułem”. Najpierw próbowałem zrobić rzeczy, aby przekonać TPTB *, że był to moduł (bez powodzenia). Więc zmieniłem „import” na „wymaganie” i to zadziałało.

Ale teraz mam około dwóch tuzinów „importów” w innych plikach, co daje mi ten sam błąd.

* Jestem pewien, że źródłem mojego problemu jest to, że nie jestem nawet pewien, co narzeka na ten problem. Przyjąłem, że to Babel 7 (ponieważ pochodzę z Babel 6 i musiałem zmienić ustawienia wstępne), ale nie jestem w 100% pewien.

Większość tego, co znalazłem dla rozwiązań, nie dotyczy prostego węzła. Jak ten tutaj:

Moduł ES6 Import podający „Nieprzechwycony błąd składni: nieoczekiwany identyfikator”

Mówi, że problem został rozwiązany przez dodanie „type = module”, ale zwykle będzie to przebiegać w HTML, którego nie mam. Próbowałem też użyć starych ustawień mojego projektu:

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

Ale pojawia się kolejny błąd: „Błąd: Pliki wtyczek / ustawień wstępnych nie mogą eksportować obiektów, tylko funkcje.”

AKTUALIZACJA: Oto zależności, od których zacząłem:

"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",
użytkownik3810626
źródło
1
Cześć, mam teraz ten sam problem. Czy możesz również podzielić się swoimi zależnościami? Może nawet różnicę przed i po aktualizacji. Mógłbym porównać z moim, aby sprawdzić, czy możemy znaleźć podobne pakiety, które mogą powodować problemy.
ryś
Właśnie zastąpiłem wszystkie „importy” słowami „wymaga” i wszystko jest teraz w porządku. Głupi, ale nie warto było tego teraz robić. Jednak zaktualizuję oryginał o zależności. Jeśli otrzymasz jakieś potencjalne szanse, sprawdzę je pod kątem mojego oryginalnego kodu.
user3810626,
1
Składnia CommonJS (wymagania i moduł.eksporty) była oryginalnym formatem dla węzła i webpack również ją obsługuje, ale składnia modułu ES6 (eksport, import) jest nowszą metodą, a teraz węzeł i webpack obsługują ją. Czytałem, że węzeł obsługuje teraz importowanie, ale tak wiele samouczków pokazuje, że wymagane są tylko czyste elementy węzłów, więc prawdopodobnie lepiej jest użyć tej składni dla węzła.
Ted Fitzpatrick
1
Wreszcie, dla mnie droga wydawała się być tak: github.com/vuejs/vue-jest/issues/134#issuecomment-461755061 ustawiania zadanej w jest.config.jscelu 'ts-jest/presets/js-with-ts'- jeszcze kilka innych kwestii, ale to rozwiązano duże. ..... tak, mój problem był związany z testowaniem ... normalne kompilacje były w porządku
ryś
Ryś, ciekawe. Sam nie korzystam z Jest. Ted, ciekawe. OK, nie pocę się.
user3810626,

Odpowiedzi:

50

Aktualizacja 2020 (węzeł 13.2.0+)

Sprawdź, czy masz zainstalowaną najnowszą wersję węzła. --experimental-modulesFlaga nie jest już konieczne. Po prostu wykonaj jedną z następujących czynności :

  • Dodaj "type": "module"do najbliższego rodzica package.json. Z tym wszystkim .js, a .mjspliki są interpretowane jako moduły ES. Możesz interpretować pojedyncze pliki jako CommonJS, używając .cjsrozszerzenia.

LUB

  • Nazwy plików z .mjsrozszerzeniem. Wszystkie inne pliki, takie jak .jsbędą interpretowane jako CommonJS, który jest domyślny, jeśli typenie jest zdefiniowany w package.json.
jabacchetta
źródło
Jeśli tego użyję, zmień ścieżkę, tak aby zawierała „js” dla wymaganego pliku, następnie zmień format instrukcji eksportowania w wymaganym pliku, a następnie weź wszystkie instrukcje „wymagane”, które zmieniłem z „importuj” - ponieważ teraz „wymaganie” jest nieznane - to zadziała, więc zaakceptuję tę odpowiedź.
user3810626
2
To nie jest tak naprawdę opcja, jeśli problem dotyczy modułu_węzła / prawda? Jakieś pomysły, jak naprawić w takim przypadku?
Trent Bing
18

Według oficjalnego dokumentu ( https://nodejs.org/api/esm.html#esm_code_import_code_statements ):

instrukcje importu są dozwolone tylko w modułach ES. Aby zobaczyć podobną funkcjonalność w CommonJS, zobacz import ().

Aby Node traktował twój plik jako moduł ES, musisz ( https://nodejs.org/api/esm.html#esm_enabling ):

  • dodaj „type”: „module” do package.json
  • dodaj flagę „--experimental-modules” do wywołania węzła
Shmekor
źródło
6

Miałem ten sam problem i następujące problemy go rozwiązały (za pomocą węzła 12.13.1):

  • Zmień rozszerzenie pliku .js na .mjs
  • Dodaj flagę --experimental-modules po uruchomieniu aplikacji.
  • Opcjonalnie: dodaj „type”: „module” w pliku package.json

więcej informacji: https://nodejs.org/api/esm.html

iseenoob
źródło
0

Miałem ten problem w nowo powstałym projekcie Express API.

Obraźliwy kod serwera w 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...'));

Oto moje zależności:

{
  "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"
  }
}

A oto biegacz, który rzucił błąd:

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

To było frustrujące, ponieważ miałem podobny projekt Express, który działał dobrze.

Rozwiązaniem było po pierwsze dodanie tej zależności:

npm install @babel/preset-env

A następnie połączyć go za pomocą babel.config.jsw katalogu głównym projektu:

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

Nie do końca rozumiem, dlaczego to działa, ale skopiowałem to z wiarygodnego źródła , więc chętnie się z tym trzymam.

halfer
źródło
-2
  1. Miałem ten sam problem, kiedy zacząłem używać babel ... Ale później miałem rozwiązanie ... Jak dotąd nie miałem problemu ... Obecnie Node v12.14.1, "@ babel / node" : „^ 7.8.4”, używam Babel-node i nodemon do wykonania (węzeł jest również w porządku ..)
  2. package.json: "start": "nodemon --exec babel-node server.js" debug ":" babel-node debug server.js "!! uwaga: server.js to mój plik wejściowy, możesz go użyć.
  3. launch.json Podczas debugowania musisz także skonfigurować plik launch.json „runtimeExecutable”: „$ {workspaceRoot} /node_modules/.bin/babel-node” !! Uwaga: plus runtimeExecutable do konfiguracji.
  4. Oczywiście w przypadku węzła babel zwykle potrzebujesz i edytujesz inny plik, taki jak plik babel.config.js / .babelrc
MrLetmein
źródło
-2

Moim rozwiązaniem było włączenie ścieżki babel-node podczas uruchamiania nodemona w następujący sposób:

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

możesz dodać w skrypcie package.json jako:

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

UWAGA: Mój plik wejściowy to index.js zastąp go plikiem wejściowym (wiele z nich ma app.js / server.js).

ishab acharya
źródło