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

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 .


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

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;


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.


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;

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

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"

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.


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


2

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

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.