Node.js - SyntaxError: importação inesperada de tokens

442

Eu não entendo o que está errado. Nó v5.6.0 NPM v3.10.6

O código:

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

O erro:

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
SofDroid
fonte
4
Use o transpiler como o Babel para usar a importação no Nodejs, pois ele não é suportado nativamente pelo nodej. Existe a melhor alternativa de importação necessária, então vá em frente.
BHUVNESH KUMAR

Respostas:

483

Atualização 3: Desde o Nó 13 , você pode usar a extensão .mjs ou definir "type": "module" em seu package.json. Você não precisa usar a --experimental-modulesbandeira.

Atualização 2: Desde o Nó 12 , você pode usar a .mjsextensão ou definir "type": "module"no seu package.json. E você precisa executar o nó com a --experimental-modulesbandeira.

Atualização: no nó 9 , é ativado atrás de um sinalizador e usa a .mjsextensão.

node --experimental-modules my-app.mjs

Embora faça importparte do ES6, infelizmente ainda não é suportado no NodeJS por padrão e só recentemente conseguiu suporte nos navegadores.

Consulte a tabela de compatibilidade do navegador no MDN e esse problema do nó .

Da atualização de James M Snell sobre os módulos ES6 no Node.js (fevereiro de 2017):

O trabalho está em andamento, mas levará algum tempo. Atualmente, estamos analisando pelo menos um ano.

Até o suporte aparecer nativamente, você precisará continuar usando as requireinstruções clássicas :

const express = require("express");

Se você realmente deseja usar os novos recursos do ES6 / 7 no NodeJS, é possível compilá-lo usando o Babel. Aqui está um servidor de exemplo .

Scimonster
fonte
2
alguém sabe se o nó 10 será enviado com o suporte ativado por padrão? (devido para a estréia no próximo mês)
Hartmut
2
@Scimonster ...... nó --experimental-modules my-app.mjs (nó: 12176) ExperimentalWarning: O carregador de módulo ESM é experimental. {Erro: Não foi possível encontrar o módulo /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs na pesquisa (internal / modules / esm / DefaultResolve.js: 23: 12) test-project / src / my-app.mjs na pesquisa (internal / modules / esm / DefaultResolve.js: 23: 12) .... lançar um aviso não pôde encontrar my-app.js .... por favor, sugira .... i versão do nó instalado 9.11.1
Leo

51
frustrante porque a maioria dos tutoriais fala sobre o uso de importação, mas quase não há suporte para isso. (Eu quero 2 horas de minhas costas lol vida)
kiwicomb123

9
@ChaimEliyah: tenho o mesmo problema no nó v11.0.0
whoami

5
Ainda requer um sinalizador na v12 nodejs.org/api/esm.html#esm_ecmascript_modules
ABabin

60

Infelizmente, o Node.js ainda não suporta o ES6 import.

Para realizar o que você está tentando fazer (importar o módulo Express), esse código deve ser suficiente

var express = require("express");

Além disso, verifique se o Express está instalado executando

$ npm install express

Consulte a documentação do Node.js. para obter mais informações sobre como aprender o Node.js.


8
importnão é necessariamente um recurso do TypeScript. TypeScript é ES6 com digitações. Coisas como importação são nativas do ES6.
borislemke

@borislemke É verdade, eu interpretei o OP um pouco errado. :) Eu vou mudar isso.
Baranskistad #

oi, eu instalei express, mas no script do arquivo package.json, o que devemos escrever? Se eu escrever "scripts": {"start": "node index.js"}, ele deverá exibir o mesmo erro. por favor me ajude.
Ravi Shah
node index.jsfunciona para mim, mas quando corro node dist/main.js, também recebo Unexpected token import.
TheFox
@ TheFox, você provavelmente tem uma importação nesse arquivo. Só porque você index.jsestá passando não significa que você dist/main.jstambém passará.
21818 baranskistad
34

Conforme mencionado em outras respostas, o Nó JS atualmente não suporta importações do ES6.

(A partir de agora, leia EDIT 2)

Habilitar importações do ES6 no nó js fornece uma solução para esse problema. Eu tentei isso e funcionou para mim.

Execute o comando:

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

Agora você precisa criar um novo arquivo (config.js) e adicionar o seguinte código.

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

Agora você pode escrever instruções de importação sem obter erros.

Espero que isto ajude.

EDITAR:

Você precisa executar o novo arquivo que você criou com o código acima. No meu caso, foi config.js. Então eu tenho que correr:

    node config.js

EDIT 2:

Ao experimentar, encontrei uma solução fácil para esse problema.

Crie um .babelrcarquivo na raiz do seu projeto.

Adicione o seguinte (e quaisquer outras predefinições de babel que você precisar, podem ser adicionadas neste arquivo):

    {
        "presets": ["env"]
    }

Instale babel-preset-envusando o comando npm install babel-preset-env --savee instale babel-cliusando o comandonpm install babel-cli -g --save

Agora, vá para a pasta em que seu servidor ou arquivo de índice existe e execute usando: babel-node fileName.js

Ou você pode executar usando npm startadicionando o seguinte código ao seu package.jsonarquivo:

    "scripts": {
        "start": "babel-node src/index.js"
    }
Neerali Acharya
fonte
Como faço isso com elétron? Eu tentei assim: "start": "babel-node electron .", mas sem sorte
tpbafk
2
@tpbafk Eu não trabalhei em elétrons. Mas encontrei algo semelhante ao seu problema javascript - Como definir o npm start para o aplicativo de elétrons com 'babel-node --presets es2015, stage-3' . Espero que ajude
Neerali Acharya
33

Erro: SyntaxError: importação inesperada de tokens ou SyntaxError: exportação inesperada de tokens


Solução: altere todas as suas importações como exemplo

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

E também mude export default = foo;paramodule.exports = foo;

supritshah1289
fonte
1
Eu gostaria que você tivesse explicado um pouco mais a parte padrão da exportação. Estou tendo problemas com essa parte. A importação funciona muito bem com a sua resposta.
21818 JoeGalind
Há uma resposta antes da minha resposta que tem uma explicação. Mas, para esclarecimento, o Nó não suporta a sintaxe ES6. Quando você diz Import ... você está usando ES6 sintaxe
supritshah1289
21

Estou chocado esmnão foi mencionado. Este pacote pequeno, mas poderoso, permite que você use um importou outro require.

Instale o esm no seu projeto

$ npm install --save esm

Atualize seu script de início do nó para usar esm

node -r esm app.js

esmsimplesmente funciona. Perdi muito tempo .mjse --experimental-modulesapenas para descobrir um .mjsarquivo não é possível importar um arquivo que use requireor module.exports. Este foi um grande problema, ao passo que esmpermite que você misture e combine e ele apenas descobre ... esmsimplesmente funciona.

thedanotto
fonte
17

No caso de você ainda não poder usar "import", aqui está como eu lidei com isso: basta traduzi-lo para um nó amigável. Exemplo:

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

É o mesmo que:

const parse = require('node-html-parser').parse;
Alberto
fonte
4
não é verdade se você é (como é provavelmente o caso) usando a exportpalavra-chave
Daniel Thompson
@DanielThompson Desculpe se isso pode ser um mal entendido, estou apenas dando uma solução alternativa para este caso, se você trabalha sem a exportpalavra - chave, de qualquer forma, obrigado pela sua observação útil!
217 Alberto Alberto
Trabalhando para mim. Obrigado
Ali Azhar
11

babel 7 proposta você pode adicionar dependências dev

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

e adicione um .babelrc na raiz

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

e adicione ao arquivo .js

require("@babel/register")

ou, se você executá-lo no cli, poderá usar o gancho de requisição como -r @ babel / register, ex.

$node -r @babel/register executeMyFileWithESModules.js
Jason Ashley
fonte
1
Instalar o @ babel / preset-env e adicioná-lo ao .babelrc fez o truque. Não é necessário o plugin @ babel / register no meu caso.
Marcos R
8

se você pode usar 'babel', tente adicionar scripts de compilação no pacote.json (- presets = es2015) como abaixo. faz pré-compilar o código de importação para es2015

"build": "babel server --out-dir build --presets=es2015 && webpack"
ASTOMUSIC
fonte
mas minha chamada para npm startprimeiro fazer a "compilação" ou primeiro a "iniciar"? (O início está definido atualmente:"nodemon src/app.js --exec \"npm run lint && node\"",
pashute
Se eu executar este cmd, mostra doen't servidor erro exist
kumaresan_sd
6

A partir de Node.js v12 (e esta é provavelmente bastante estável agora, mas ainda marcado "experimental"), você tem um par de opções para utilizar ESM ( E CMA S cript M odules) em Node.js (para arquivos, há uma terceira maneira de avaliar seqüências de caracteres), eis o que a documentação diz:

O --experimental-modulessinalizador pode ser usado para ativar o suporte para módulos ECMAScript (módulos ES).

Uma vez ativado, o Node.js tratará o seguinte como módulos ES quando transmitido nodecomo entrada inicial ou quando referenciado por importinstruções no código do módulo ES:

  • Arquivos terminando em .mjs.

  • Arquivos que terminam em .jsou arquivos sem extensão, quando o package.jsonarquivo pai mais próximo contém um campo de nível superior "type"com um valor de "module".

  • Strings passadas como um argumento para --evalou --print, ou canalizadas para nodevia STDIN, com a bandeira --input-type=module.

O Node.js tratará como CommonJS todas as outras formas de entrada, como .jsarquivos nos quais o package.jsonarquivo pai mais próximo não contém "type" campo de nível superior ou entrada de sequência sem o sinalizador --input-type. Esse comportamento é para preservar a compatibilidade com versões anteriores. No entanto, agora que o Node.js suporta os módulos CommonJS e ES, é melhor ser explícito sempre que possível. O Node.js tratará o seguinte como CommonJS quando passado nodecomo entrada inicial ou quando referenciado por importinstruções no código do módulo ES:

  • Arquivos terminando em .cjs.

  • Arquivos que terminam em .jsou arquivos sem extensão, quando o package.jsonarquivo pai mais próximo contém um campo de nível superior "type"com um valor de "commonjs".

  • Strings passadas como um argumento para --evalou --print, ou canalizadas para nodevia STDIN, com a bandeira --input-type=commonjs.

TJ Crowder
fonte
3

Quando eu comecei com o express, sempre quis uma solução para usar a importação, em vez de exigir

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

Muitas vezes passam por esta linha: - Unfortunately, Node.js doesn't support ES6's import yet.

Agora, para ajudar outros, crio novas duas soluções aqui

1) esm : -

O carregador de módulo ECMAScript brilhantemente simples, sem babel e sem pacote. vamos fazer funcionar

  yarn add esm / npm install esm

crie start.js ou use seu espaço para nome

 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

Mudança no seu package.josncaminho de passagem destart.js

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

2) Babel js : -

Isso pode ser dividido em 2 partes

a) Solução 1 graças a timonweb.com

b) Solução 2

use Babel 6 (versão mais antiga do babel-preset-stage-3 ^ 6.0 ) crie um .babelrcarquivo na sua pasta raiz

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

Instale o babel-preset-stage-3

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

Mudança no 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"
},

Inicie seu servidor

yarn start / npm start

Oooh não, criamos um novo problema

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

Este erro ocorre somente quando você usa async / waitit no seu código. Em seguida, use o polyfill que inclui um tempo de execução do regenerador customizado e core-js. adicione em cima deindex.js

import "babel-polyfill"

Isso permite que você use assíncrono / espera

use Babel 7

É necessário atualizar tudo em seu projeto, e começar com babel 7 .babelrc

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

Alguma mudança no 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"
....
}

e use import "@babel/polyfill"no ponto de partida

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

Você está pensando o porquê start:dev

A sério. É uma boa pergunta se você é novo. A cada mudança que você sempre usa yarn start:devno servidor de inicialização, use como servidor de desenvolvimento todas as alterações no servidor de reinicialização automaticamente para obter mais informações sobre o nodemon

Ashok
fonte
2

No meu caso, ele estava cuidando do .babelrcarquivo e deveria conter algo como isto:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
Ghita Tomoiaga
fonte