Node.js - SyntaxError: importación de token inesperada

442

No entiendo lo que está mal. Nodo v5.6.0 NPM v3.10.6

El código:

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

El error:

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
fuente
44
Use el transpilador como Babel para usar la importación en Nodejs, ya que no es compatible de forma nativa en nodejs. Hay una mejor alternativa de importación que se requiere, así que vaya con eso.
BHUVNESH KUMAR

Respuestas:

483

Actualización 3: desde el Nodo 13 , puede usar la extensión .mjs o establecer "type": "module" en su package.json. Usted no necesita utilizar la --experimental-modulesbandera.

Actualización 2: desde el Nodo 12 , puede usar la .mjsextensión o establecerla "type": "module"en su package.json. Y necesita ejecutar el nodo con la --experimental-modulesbandera.

Actualización: en el Nodo 9 , se habilita detrás de una bandera y usa la .mjsextensión.

node --experimental-modules my-app.mjs

Si bien importes parte de ES6, desafortunadamente aún no es compatible con NodeJS de manera predeterminada, y solo recientemente ha sido compatible con los navegadores.

Consulte la tabla de compatibilidad del navegador en MDN y este problema de Nodo .

De la actualización de James M Snell sobre los módulos ES6 en Node.js (febrero de 2017):

El trabajo está en progreso, pero llevará algún tiempo. Actualmente estamos analizando alrededor de un año al menos.

Hasta que el soporte se muestre de forma nativa, deberá continuar utilizando requiredeclaraciones clásicas :

const express = require("express");

Si realmente desea utilizar las nuevas funciones de ES6 / 7 en NodeJS, puede compilarlo con Babel. Aquí hay un servidor de ejemplo .

Scimonster
fuente
2
¿Alguien sabe si el nodo 10 se enviará con el soporte habilitado de forma predeterminada? (debutará el próximo mes)
Hartmut
2
@Scimonster ...... nodo --experimental-modules my-app.mjs (nodo: 12176) Advertencia experimental: el cargador de módulos ESM es experimental. {Error: no se puede encontrar el módulo /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs en la búsqueda (internal / modules / esm / DefaultResolve.js: 23: 12) test-project / src / my-app.mjs en la búsqueda (internal / modules / esm / DefaultResolve.js: 23: 12) ... lanzando una advertencia no se pudo encontrar my-app.js .... por favor sugiera .... i nodo instalado versión 9.11.1
Leo

51
frustrante porque la mayoría de los tutoriales por ahí hablan de usar importación, pero casi no hay soporte para ello. (Quiero 2 horas de mi vida jajaja)
kiwicomb123

99
@ChaimEliyah: tengo el mismo problema en el nodo v11.0.0
whoami

55
Todavía requiere una bandera en v12 nodejs.org/api/esm.html#esm_ecmascript_modules
ABabin

60

Desafortunadamente, Node.js aún no es compatible con ES6 import.

Para lograr lo que intenta hacer (importar el módulo Express), este código debería ser suficiente

var express = require("express");

Además, asegúrese de tener Express instalado ejecutando

$ npm install express

Consulte los documentos de Node.js para obtener más información sobre el aprendizaje de Node.js.


8
importno es necesariamente una característica de TypeScript. TypeScript es ES6 con tipings. Así que cosas como importar son nativas de ES6.
borislemke

@borislemke Es cierto, interpreté el OP un poco mal. :) Lo cambiaré.
baranskistad

hola, instalé express pero en la secuencia de comandos del archivo package.json, ¿qué debemos escribir? Si escribo "scripts": {"start": "node index.js"}, debería mostrar el mismo error. por favor, ayúdame.
Ravi Shah
node index.jsfunciona para mí, pero cuando corro node dist/main.jstambién me sale Unexpected token import.
TheFox
@TheFox probablemente tenga una importación en ese archivo. El hecho de que index.jsesté pasando no significa que dist/main.jstambién pasará.
baranskistad
34

Como se mencionó en otras respuestas, el nodo JS actualmente no es compatible con las importaciones ES6.

(A partir de ahora, lea EDITAR 2)

Habilitar las importaciones de ES6 en el nodo js proporciona una solución a este problema. He intentado esto y funcionó para mí.

Ejecute el comando:

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

Ahora necesita crear un nuevo archivo (config.js) y agregarle el siguiente código.

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

Ahora puede escribir declaraciones de importación sin obtener ningún error.

Espero que esto ayude.

EDITAR:

Debe ejecutar el nuevo archivo que creó con el código anterior. En mi caso lo fue config.js. Entonces tengo que correr:

    node config.js

EDITAR 2:

Mientras experimentaba, encontré una solución fácil para este problema.

Cree un .babelrcarchivo en la raíz de su proyecto.

Agregue lo siguiente (y cualquier otro preajuste de babel que necesite, se puede agregar en este archivo):

    {
        "presets": ["env"]
    }

Instalar babel-preset-envusando el comando npm install babel-preset-env --save, y luego instalar babel-cliusando el comandonpm install babel-cli -g --save

Ahora, vaya a la carpeta donde existe su servidor o archivo de índice y ejecútelo usando: babel-node fileName.js

O puede ejecutar usando npm startagregando el siguiente código a su package.jsonarchivo:

    "scripts": {
        "start": "babel-node src/index.js"
    }
Neerali Acharya
fuente
¿Cómo hago esto con el electrón? He intentado de esta manera: "start": "babel-node electron .", pero no hubo suerte
tpbafk
2
@tpbafk No he trabajado en electron. Pero encontré algo similar a su problema javascript: cómo configurar npm start para la aplicación de electrones con 'babel-node --presets es2015, stage-3' . Espero que ayude
Neerali Acharya
33

Error: SyntaxError: importación de token inesperada o SyntaxError: exportación de token inesperada


Solución: cambie todas sus importaciones como ejemplo

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

Y también cambia tu export default = foo;amodule.exports = foo;

supritshah1289
fuente
1
Desearía que hubieras explicado un poco más la parte predeterminada de exportación. Estoy teniendo problemas con esa parte. La importación funciona muy bien con tu respuesta.
JoeGalind
Hay una respuesta antes de mi respuesta que tiene una explicación. Pero para aclarar, Node no admite la sintaxis de ES6. Cuando dices Importar ... estás usando la sintaxis ES6
supritshah1289
22

Estoy sorprendido de que esmno se haya mencionado. Este pequeño pero poderoso paquete te permite usar cualquiera importo require.

Instala esm en tu proyecto

$ npm install --save esm

Actualice su script de inicio de nodo para usar esm

node -r esm app.js

esmsolo funciona Perdí una TONELADA de tiempo .mjsy --experimental-modulessolo para descubrir que un .mjsarchivo no puede importar un archivo que usa requireo module.exports. Este fue un gran problema, mientras esmque le permite mezclar y combinar y simplemente lo resuelve ... esmsimplemente funciona.

thedanotto
fuente
17

En caso de que todavía no pueda usar "importar", así es como lo manejé: solo traduzca a un nodo amigable requerido. Ejemplo:

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

Es lo mismo que:

const parse = require('node-html-parser').parse;
Alberto
fuente
44
no es cierto si está utilizando (como es probable) la exportpalabra clave
Daniel Thompson
@DanielThompson Lo siento si esto puede ser un malentendido, solo estoy dando una solución para este caso, si trabajas sin la exportpalabra clave, de todos modos, ¡gracias por tu útil nota!
Alberto
Trabajando para mi Gracias
Ali Azhar
11

La propuesta de Babel 7 puede agregar dependencias de desarrollo

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

y agregue un .babelrc en la raíz

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

y agregar al archivo .js

require("@babel/register")

o si lo ejecuta en el cli, puede usar el gancho require como -r @ babel / register, ej.

$node -r @babel/register executeMyFileWithESModules.js
Jason Ashley
fuente
1
Instalar @ babel / preset-env y agregarlo a .babelrc hizo el truco. No necesito el complemento @ babel / register en mi caso.
Marcos R
8

si puede usar 'babel', intente agregar scripts de compilación en package.json (- presets = es2015) como se muestra a continuación. hace precompilar el código de importación a es2015

"build": "babel server --out-dir build --presets=es2015 && webpack"
ASTOMUSIC
fuente
pero, ¿mi llamado a npm starthacer primero la "compilación", o primero al "inicio"? (El inicio está definido actualmente:"nodemon src/app.js --exec \"npm run lint && node\"",
pashute
si ejecuto este cmd, muestra que el servidor no existe error
kumaresan_sd
6

A partir de Node.js v12 (y esto es probablemente bastante estable, pero todavía marcado como "experimental"), que tiene un par de opciones para el uso de ESM ( E CMA S cripta M odules) en Node.js (para archivos, hay una tercera forma de evaluar cadenas), esto es lo que dice la documentación :

El --experimental-modulesindicador se puede utilizar para habilitar la compatibilidad con los módulos ECMAScript (módulos ES).

Una vez habilitado, Node.js tratará lo siguiente como módulos ES cuando se les pase nodecomo entrada inicial, o cuando se haga referencia a ellos mediante importdeclaraciones dentro del código del módulo ES:

  • Archivos que terminan en .mjs.

  • Archivos que terminan en .js, o archivos sin extensión, cuando el package.jsonarchivo principal más cercano contiene un campo de nivel superior "type"con un valor de "module".

  • Cadenas pasadas como argumento a --evalo --print, o canalizado a nodetravés STDIN, con la bandera --input-type=module.

Node.js tratará como CommonJS todas las demás formas de entrada, como los .jsarchivos donde el package.jsonarchivo principal más cercano no contiene un "type" campo de nivel superior , o la entrada de cadena sin la bandera --input-type. Este comportamiento es para preservar la compatibilidad con versiones anteriores. Sin embargo, ahora que Node.js admite los módulos CommonJS y ES, es mejor ser explícito siempre que sea posible. Node.js tratará lo siguiente como CommonJS cuando se pase nodecomo entrada inicial, o cuando se haga referencia a él mediante importdeclaraciones dentro del código del módulo ES:

  • Archivos que terminan en .cjs.

  • Archivos que terminan en .js, o archivos sin extensión, cuando el package.jsonarchivo principal más cercano contiene un campo de nivel superior "type"con un valor de "commonjs".

  • Cadenas pasadas como argumento a --evalo --print, o canalizado a nodetravés STDIN, con la bandera --input-type=commonjs.

TJ Crowder
fuente
3

Cuando comencé con express siempre quise una solución para usar import en lugar de requerir

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

Muchas veces pasan por esta línea: - Unfortunately, Node.js doesn't support ES6's import yet.

Ahora para ayudar a otros, creo dos nuevas soluciones aquí

1) esm : -

El cargador de módulos ECMAScript brillantemente simple, sin babel y sin paquete. hagámoslo funcionar

  yarn add esm / npm install esm

crea start.js o usa tu espacio de nombres

 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

Cambio en su package.josncamino de paso 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 : -

Esto se puede dividir en 2 partes

a) Solución 1 gracias a timonweb.com

si) Solución 2

use Babel 6 (versión anterior de babel-preset-stage-3 ^ 6.0 ) cree el .babelrcarchivo en su carpeta raíz

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

Instalar babel-preset-stage-3

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

Cambio en 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"
},

Inicia tu servidor

yarn start / npm start

Oooh no, creamos un nuevo problema

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

Este error solo se produce cuando usa async / await en su código. Luego use polyfill que incluye un tiempo de ejecución de regenerador personalizado y core-js. agregar encima deindex.js

import "babel-polyfill"

Esto le permite usar async / await

usar Babel 7

Necesita actualizar cada cosa en su proyecto, comencemos con babel 7 .babelrc

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

Algún cambio en 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"
....
}

y usar import "@babel/polyfill"en el punto de inicio

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

¿Estás pensando por qué? start:dev

Seriamente. Es buena pregunta si eres nuevo. Cada cambio que se hace con el servidor de inicio cada vez que se usa yarn start:devcomo servidor de desarrollo, cada cambio reinicia el servidor automáticamente para obtener más información sobre nodemon

Ashok
fuente
2

En mi caso, estaba cuidando el .babelrcarchivo, y debería contener algo como esto:

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