NodeJS planea admitir módulos de importación / exportación es6 (es2015)

275

He estado buscando en Internet sin una respuesta clara para esto.

Actualmente, NodeJS usa solo la sintaxis CommonJS para cargar módulos, y si realmente quiere usar la sintaxis estándar de módulos ES2015, debe transpilarla de antemano o usar un cargador de módulos externo en tiempo de ejecución.

Actualmente no soy demasiado positivo para usar ninguno de esos dos métodos, ¿los encargados de mantenimiento de NodeJS incluso planean admitir módulos ES2015 o no? No he encontrado ninguna pista sobre esto.

Por el momento, NodeJS 6.x afirma que admite el 96% de las funciones de ES2015, pero no hay ninguna referencia a los módulos ( enlace de soporte de NodeJS ES2105 ).

¿Sabes si NodeJS admitirá estos módulos listos para usar, en un futuro cercano?

Zorgatone
fuente
2
Buscar en Google node es2015 modulesmuestra lo siguiente como uno de los mejores resultados: github.com/nodejs/node/wiki/ES6-Module-Detection-in-Node .
Felix Kling
66
Personalmente, votaría para cerrar esta pregunta como "demasiado localizada", pero esa estrecha razón ya no existe. Digamos que Node logra implementar módulos ES6 mañana. ¿Vas a eliminar tu pregunta entonces porque ya no es relevante? ¿O al menos lo actualizarás? No creo que una pregunta sea adecuada para SO si ya sabe que estará desactualizada o necesita actualizarse "pronto". Pero esa es solo mi opinión y parece que hay otros que piensan lo contrario, lo cual está bien para mí :) (fwiw, por sí misma la pregunta es, por supuesto, importante e interesante)
Felix Kling
2
Sin embargo, desearía que hubiera un lugar en el Universo Stack para preguntas como esta. Puede que técnicamente no encaje aquí, pero no sé si estoy de acuerdo en que realmente está "basado en opiniones". OP está buscando una respuesta específica a una pregunta específica, pero que estará (en algún momento) desactualizada.
Wonko el cuerdo
55
Fraseología alternativa de esta pregunta: "¿Cuál es el estado del soporte de node.js para los módulos ES6?" La respuesta a muchas preguntas SO cambia con el tiempo a medida que la tecnología evoluciona. Yo también tuve problemas para encontrar la respuesta hasta que llegué aquí.
Joe Lapp
44
@FelixKling, supongo que querer cerrar esta pregunta habría sido una decisión muy equivocada, ya que hasta ahora 211 personas han resultado ser lo suficientemente problemáticas como para votar.
Muhammad Umer

Respuestas:

302

Nodo 13.2.0 y superior

NodeJS 13.2.0 ahora es compatible con los módulos ES sin una marca 🎉 Sin embargo, la implementación todavía está marcada como experimental, por lo que debe usarse con precaución en la producción.

Para habilitar el soporte de ESM en 13.2.0, agregue lo siguiente a su package.json:

{
  "type": "module"
}

Todo .js, .mjs(o archivos sin extensión) serán tratados como ESM.

Hay varias opciones diferentes además de la suscripción completa package.json, todas las cuales se detallan en la Documentación para 13.2.0 .

Nodo 13.1.0 y abajo

Aquellos que todavía usan versiones anteriores de Node pueden querer probar el cargador de módulos esm , que es una implementación lista para producción de la especificación de módulos ES para NodeJS:

node -r esm main.js

Actualizaciones detalladas ...

23 abril 2019

Un RP recientemente aterrizó para cambiar la forma en que se detectan los módulos ES: https://github.com/nodejs/node/pull/26745

Todavía está detrás de la --experimental-modulesbandera, pero hay cambios importantes en la forma en que se pueden cargar los módulos:

  • package.typeque puede ser moduleocommonjs
    • type: "commonjs":
      • .js se analiza como commonjs
      • el valor predeterminado para el punto de entrada sin una extensión es commonjs
    • type: "module":
      • .js se analiza como esm
      • no admite cargar JSON o Native Module de forma predeterminada
      • el valor predeterminado para el punto de entrada sin una extensión es esm
  • --type=[mode]para permitirle establecer el tipo en el punto de entrada. Se anulará package.typepara el punto de entrada.
  • Una nueva extensión de archivo .cjs.
    • Esto es específicamente para admitir la importación de commonjs en el modulemodo.
    • esto es solo en el cargador de esm, el cargador commonjs permanece intacto, pero la extensión funcionará en el cargador anterior si usa la ruta completa del archivo.
  • --es-module-specifier-resolution=[type]
    • las opciones son explicit(por defecto) ynode
    • de manera predeterminada, nuestro cargador no permitirá extensiones opcionales en la importación, la ruta para un módulo debe incluir la extensión si hay una
    • de manera predeterminada, nuestro cargador no permitirá importar directorios que tengan un archivo de índice
    • los desarrolladores pueden usar --es-module-specifier-resolution=nodepara habilitar el algoritmo de resolución del especificador commonjs
    • Esta no es una "característica" sino más bien una implementación para la experimentación. Se espera que cambie antes de quitar la bandera
  • --experimental-json-loader
    • la única forma de importar json cuando "type": "module"
    • cuando se habilite, todos import 'thing.json'pasarán por el cargador experimental independientemente del modo
    • basado en whatwg / html # 4315
  • Puede usar package.mainpara establecer un punto de entrada para un módulo
    • las extensiones de archivo utilizadas en main se resolverán según el tipo de módulo

17 enero 2019

El nodo 11.6.0 todavía enumera los módulos ES como experimentales, detrás de una bandera.

13 de septiembre de 2017

NodeJS 8.5.0 ha sido lanzado con soporte para archivos mjs detrás de una bandera:

node --experimental-modules index.mjs

El plan para esto es eliminar la bandera de la versión v10.0 LTS.

- Información desactualizada. Mantenido aquí para fines históricos

8 de septiembre de 2017

La rama maestra NodeJS se ha actualizado con soporte inicial para módulos ESM:
https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5

Esto debería estar disponible en la última noche (se puede instalar a través de nvm para que se ejecute junto con su instalación existente):
https://nodejs.org/download/nightly/

Y habilitado detrás de la --experimental-modulesbandera:

package.json

{
  "name": "testing-mjs",
  "version": "1.0.0",
  "description": "",
  "main": "index.mjs" <-- Set this to be an mjs file
}

Entonces corre:

node --experimental-modules .

Febrero 2017:

https://medium.com/@jasnell/an-update-on-es6-modules-in-node-js-42c958b890c#.6ye7mtn37

Los chicos de NodeJS han decidido que la solución menos mala es usar la .mjsextensión de archivo. La conclusión de esto es:

En otras palabras, dados dos archivos foo.jsy bar.mjs, usando import * from 'foo'tratará foo.jscomo CommonJS mientras import * from 'bar' tratará bar.mjscomo un Módulo ES6

Y en cuanto a las líneas de tiempo ...

En el momento actual, todavía hay una serie de problemas de especificación e implementación que deben suceder en el lado de ES6 y la máquina virtual antes de que Node.js pueda comenzar a trabajar en una implementación compatible de módulos ES6. El trabajo está en progreso, pero llevará algún tiempo. Actualmente estamos analizando alrededor de un año al menos .

Octubre 2016:

Uno de los desarrolladores de Node.JS asistió recientemente a una reunión TC-39 y escribió un excelente artículo sobre los bloqueadores para la implementación de Node.JS:

https://hackernoon.com/node-js-tc-39-and-modules-a1118aecf95e

La conclusión básica de eso es:

  • Los módulos ES se analizan estáticamente, se evalúan CommonJS
  • Los módulos CommonJS permiten exportaciones de parches de mono, los módulos ES actualmente no
  • Es difícil detectar qué es un módulo ES y qué es CommonJS sin alguna forma de entrada del usuario, pero lo están intentando.
  • *.mjs parece la solución más probable, a menos que puedan detectar con precisión un módulo ES sin la intervención del usuario

- Respuesta original -

Esta ha sido una papa caliente durante bastante tiempo. La conclusión es que sí, Node eventualmente admitirá la sintaxis ES2015 para importar / exportar módulos, muy probablemente cuando la especificación para cargar módulos esté finalizada y acordada.

Aquí hay una buena descripción de lo que está deteniendo a NodeJS. Esencialmente, deben asegurarse de que la nueva especificación funcione para Node, que es principalmente condicional, carga síncrona y también HTML, que es principalmente asíncrono.

Nadie lo sabe con certeza en este momento, pero imagino que Node admitirá import/exportla carga estática, además de la nueva System.importpara la carga dinámica, al tiempo que conserva el requirecódigo heredado.

Aquí hay algunas propuestas sobre cómo Node podría lograr esto:

CodificaciónIntriga
fuente
38
Acerca de .mjsextensión: We have affectionately called these “Michael Jackson Script” files in the past. En caso de que escuches a alguien hablando de artistas pop durante la charla de JS.
Jeewes
1
No veo por qué cambiar la sintaxis de importación no es suficiente. ¿Una sintaxis para importar es (la 'correcta') y otra para importar cjs? En otras palabras, dados dos archivos foo.js y bar.js, import * from 'foo'tratarán a foo.js como CommonJS import * as bar from 'bar'tratará a bar.js como un Módulo ES6. ¿Alguien puede explicarlo?
Corey Alix
1
La sintaxis de @CoreyAlix generalmente no se cambiará para admitir un entorno. Esto realmente solo afecta a Node después de todo. Además, la sintaxis es un poco no intuitiva. ¿Cómo accedo a las exportaciones en la sintaxis propuesta?
CodingIntrigue
Para ser claros, no es "mi" propuesta, estoy copiando lo que el mecanografiado ya está haciendo. Para responder a su pregunta, puede acceder a las exportaciones con "bar": bar.foobar () import {foo as Foo} desde "./foo" es el mecanismo para identificar un módulo ES6. var Foo = require ("./ foo") es el mecanismo para identificar el módulo CJS. En Typecript, la salida de commonjs se ve así: var mod1_1 = require ("./ mod1"); exportaciones.mod1 = mod1; El resultado de ES6 se ve así: import {mod1} desde "./mod1"; export {mod1}
Corey Alix
1
Sería realmente interesante en una actualización del Nodo 10 de esta respuesta. ¿La característica hizo el corte, o todavía está detrás de una bandera?
dcorking