SyntaxError: Não é possível usar a instrução de importação fora de um módulo

53

Eu tenho um projeto ApolloServer que está me dando problemas, então pensei em atualizá-lo e ter problemas ao usar o Babel mais recente. Meu "index.js" é:

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

E quando o executo, recebo o erro "SyntaxError: Não é possível usar a declaração de importação fora de um módulo". Primeiro, tentei fazer as coisas para convencer o TPTB * de que este era um módulo (sem sucesso). Então eu mudei a "importação" para uma "exigência" e isso funcionou.

Mas agora tenho cerca de duas dúzias de "importações" em outros arquivos, dando-me o mesmo erro.

* Tenho certeza que a raiz do meu problema é que nem tenho certeza do que está reclamando sobre o problema. Eu meio que presumi que fosse o Babel 7 (já que eu sou do Babel 6 e precisei alterar as predefinições), mas não tenho 100% de certeza.

A maior parte do que encontrei para soluções não parece se aplicar ao Node direto. Como este aqui:

Importação do módulo ES6 fornecendo "Untaught SyntaxError: identificador inesperado"

Diz que foi resolvido adicionando "type = module", mas isso normalmente ocorre no HTML, do qual não tenho nenhum. Também tentei usar as predefinições antigas do meu projeto:

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

Mas isso me dá outro erro: "Erro: arquivos de plug-in / predefinidos não podem exportar objetos, apenas funções".

UPDATE: Aqui estão as dependências com as quais eu comecei:

"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
fonte
11
Olá, tendo o mesmo problema no momento. Você também pode compartilhar suas dependências? Talvez até mesmo um diff antes e depois da sua atualização. Eu poderia verificar contra o meu para ver se conseguimos encontrar pacotes semelhantes que possam causar o problema.
Lynx
Acabei de substituir todas as "importações" por "requer" e está tudo bem agora. Burro, mas não valeu a pena o esforço para descobrir agora. Vou atualizar o original com dependências, no entanto. Se você receber alguma dica, eu as verificarei em relação ao meu código original.
user3810626
11
A sintaxe CommonJS (require e module.exports) era o formato original para o nó e o webpack também o suporta, mas a sintaxe do módulo ES6 (exportação, importação) é a maneira mais nova e agora o nó e o webpack o suportam. Eu li que o nó suporta importação agora, mas muitos tutoriais mostram a necessidade de itens puros do nó que provavelmente é melhor usar essa sintaxe para o nó.
Ted Fitzpatrick
11
Finalmente, para mim, o caminho a seguir parecia ser o seguinte: github.com/vuejs/vue-jest/issues/134#issuecomment-461755061 Definir a predefinição jest.config.jspara 'ts-jest/presets/js-with-ts'- ainda tem alguns outros problemas, mas isso resolveu o grande problema. ..... uh sim, o meu problema estava testando relacionados ... o normal de construções eram muito bem
lynx
Lynx, Interessante. Não estou usando Jest, eu mesmo. Ted, interessante. OK, não vou suar.
user3810626

Respostas:

52

Atualização 2020 (nó 13.2.0 ou posterior)

Verifique se você tem a versão mais recente do Node instalada. A --experimental-modulesbandeira não é mais necessária. Simplesmente siga um destes procedimentos :

  • Adicione "type": "module"ao pai mais próximo package.json. Com isso, todos os arquivos .jse .mjssão interpretados como módulos ES. Você pode interpretar arquivos individuais como CommonJS usando a .cjsextensão

OU

  • Nomeie explicitamente os arquivos com a .mjsextensão. Todos os outros arquivos, como .jsserão interpretados como CommonJS, que é o padrão se typenão estiver definido em package.json.
jabacchetta
fonte
Se eu usar isso, altere o caminho para incluir os "js" do arquivo necessário, altere o formato das instruções de exportação no arquivo necessário e, em seguida, faça com que todas as instruções "require" que eu mudei de "import" - porque agora "exigir" é desconhecido - isso funcionará, então aceitarei esta resposta.
User3810626 10/04
2
Esta não é realmente uma opção se o problema estiver em node_modules / certo? Alguma idéia de como corrigir nesse caso?
Trent Bing
18

De acordo com o documento oficial ( https://nodejs.org/api/esm.html#esm_code_import_code_statements ):

As instruções de importação são permitidas apenas nos módulos ES. Para funcionalidade semelhante no CommonJS, consulte import ().

Para fazer o Node tratar seu arquivo como um módulo ES, você precisa ( https://nodejs.org/api/esm.html#esm_enabling ):

  • adicione "type": "module" ao package.json
  • adicione o sinalizador "--experimental-modules" à chamada do nó
shmekor
fonte
6

Eu tive o mesmo problema e o seguinte foi corrigido (usando o nó 12.13.1):

  • Altere a extensão de arquivo .js para .mjs
  • Adicione o sinalizador --experimental-modules ao executar seu aplicativo.
  • Opcional: adicione "type": "module" em seu package.json

mais informações: https://nodejs.org/api/esm.html

iseenoob
fonte
0

Eu tive esse problema em um projeto de API Express iniciante.

O código do servidor incorreto em 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...'));

Aqui estavam minhas dependências:

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

E aqui estava o corredor que lançou o erro:

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

Isso foi frustrante, pois eu tinha um projeto Express semelhante que funcionou bem.

A solução foi primeiramente adicionar esta dependência:

npm install @babel/preset-env

E então conectá-lo usando um babel.config.jsna raiz do projeto:

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

Não entendo muito bem por que isso funciona, mas copiei de uma fonte autorizada , por isso estou feliz em continuar.

halter
fonte
Sim, meu problema era que o código tinha várias predefinições e eu nunca consegui atingir o equilíbrio certo entre as coisas que eu queria e as que não queria / que quebraram coisas.
user3810626
Venho enfrentando falhas de JS confusas o dia todo @ user3810626 - suspeito que meu problema é que sou bastante novo na linguagem e no ecossistema e preciso deixar um pouco de aprendizado de lado por enquanto para que as coisas funcionem. Como chegar ...:-)
halfer
11
Boa sorte! É uma selva lá fora! (Quero dizer, literalmente, o ecossistema JS é uma selva ...)
user3810626
-2
  1. Eu tive o mesmo problema quando comecei a usar o babel ... Mas, mais tarde, eu tinha uma solução ... não tinha mais o problema até agora ... Atualmente, o nó v12.14.1, "@ babel / node" : "^ 7.8.4", eu uso babel-node e nodemon para executar (o nó também está bom ..)
  2. package.json: "start": "nodemon --exec babel-node server.js" debug ":" babel-node debug server.js "!! note: server.js é o meu arquivo de entrada, você pode usar o seu.
  3. launch.json Ao depurar, você também precisa configurar o arquivo launch.json "runtimeExecutable": "$ {workspaceRoot} /node_modules/.bin/babel-node" !! note: plus runtimeExecutable na configuração.
  4. Obviamente, com o babel-node, você normalmente também precisa e edita outro arquivo, como o arquivo babel.config.js / .babelrc
MrLetmein
fonte
-2

Minha solução foi incluir o caminho do nó babel ao executar o nodemon da seguinte maneira:

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

você pode adicionar seu script package.json como:

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

NOTA: Meu arquivo de entrada é index.js, substitua-o pelo seu arquivo de entrada (muitos têm app.js / server.js).

ishab acharya
fonte