Anunciamos soporte para módulos ECMAScript en Node.js

Node.js 13.2.0 viene con soporte ECMAScript para módulos conocidos por su sintaxis de importación y exportación. Anteriormente, esta funcionalidad estaba detrás de la bandera --experimental-modules , que ya no es necesaria. Sin embargo, la implementación aún es experimental y está sujeta a cambios.


De un traductor: esta característica tan esperada finalmente nos permitirá usar la sintaxis modular estándar ya disponible en los navegadores modernos, y ahora también en Node.js sin banderas y transpiladores


La activación


Node.js procesará el código como módulos ES en los siguientes casos:


  • Archivos con la extensión .mjs
  • Archivos con la extensión .js o sin la extensión, siempre que el package.json principal.json más cercano a ellos contenga el valor "type": "module"
  • Código pasado a través del argumento —-eval o STDIN, junto con el indicador de —-input-type=module

En todos los demás casos, el código se considerará CommonJS. Esto se aplica a los archivos .js sin "type": "module" en el package.json más cercano y al código pasado a través de la línea de comando sin especificar --input-type . Esto se hace para mantener la compatibilidad con versiones anteriores. Sin embargo, dado que ahora tenemos dos tipos de módulos, CommonJS y ES, será mejor especificar el tipo de módulos explícitamente.


Puede marcar explícitamente su código como CommonJS con las siguientes características:


  • Archivos con la extensión .cjs
  • Archivos con la extensión .js o sin extensión, siempre que el package.json padre más package.json contenga el valor "type": "“commonjs”"
  • Código pasado a través del argumento --eval o STDIN con la --input-type=commonjs explícita --input-type=commonjs

Para obtener más información sobre estas características, consulte las secciones de documentación "Alcance del paquete y Extensiones de archivo" y --input-type


Importación y exportación de sintaxis


En el contexto del módulo ES, puede usar import , apuntando a otros archivos Javascript. Se pueden especificar en uno de los siguientes formatos:


  • URL relativa: "./file.mjs"
  • URL absoluta c file:// , por ejemplo, "file:///opt/app/file.mjs"
  • Nombre del paquete: "es-module-package"
  • La ruta al archivo dentro del paquete: "es-module-package/lib/file.mjs"

En las importaciones, puede usar valores predeterminados ( import _ from "es-module-package" ) y valores con nombre ( import { shuffle } from "es-module-package" ), así como importar todo como un espacio de nombres ( import * as fs from "fs" ). Todos los paquetes integrados de Node.js, como fs o path , admiten los tres tipos de importaciones.


Las importaciones que apuntan al código CommonJS (es decir, todos los JavaScript actuales escritos para Node.js require y module.exports ) solo pueden usar la opción predeterminada ( import _ from "commonjs-package" ).


La importación de otros formatos de archivo como JSON y WASM sigue siendo experimental, y requiere los indicadores --experimental-json-modules y --experimental-wasm-modules respectivamente. Sin embargo, puede descargar estos archivos utilizando la API module.createRequire , que está disponible sin module.createRequire adicionales.


En sus módulos ES, puede usar la palabra clave export para exportar valores predeterminados y con nombre.


Las expresiones dinámicas con import() se pueden usar para cargar módulos ES desde CommonJS o código ES. Tenga en cuenta que import() no devuelve un módulo sino su promesa (Promise).


import.meta.url está disponible en los módulos, que contiene la URL absoluta del módulo ES actual.


Archivos y el nuevo campo "tipo" en package.json


Agregue "type": "module" al package.json de su proyecto, y Node.js comenzará a percibir todos los archivos .js de su proyecto como módulos ES.


Si algunos archivos de su proyecto todavía usan CommonJS y no puede migrar todo el proyecto a la vez, puede usar la extensión .cjs para este código o colocarlo en un directorio separado y agregar package.json contenga { "type": "commonjs" } , que le dice a Node.js que debe tratarse como CommonJS.


Para cada archivo descargado, Node.js buscará package.json en el directorio que lo contiene, luego un nivel más y así sucesivamente hasta que llegue al directorio raíz. Este mecanismo es similar a cómo Babel .babelrc archivos Babel .babelrc . Este enfoque permite que Node.js use package.json como fuente de varios metadatos sobre el paquete y la configuración, de forma similar a cómo ya funciona en Babel y otras herramientas.


Recomendamos que todos los desarrolladores de paquetes especifiquen un campo de type , incluso si commonjs está escrito commonjs .


Los puntos de entrada del paquete y el campo "exportaciones" en package.json


Ahora tenemos dos campos para especificar el punto de entrada en el paquete: main y exports . El campo main es compatible con todas las versiones de Node.js, pero sus capacidades son limitadas: con él puede definir solo un punto de entrada principal en el paquete. El nuevo campo de exports también le permite definir el punto de entrada principal, así como rutas adicionales. Esto proporciona encapsulación adicional para paquetes donde solo las rutas de exports explícitas están disponibles para importar desde fuera del paquete. exports aplican a ambos tipos de módulos, CommonJS y ES, sin importar si se usan mediante require o import .


Esta funcionalidad permitirá que las importaciones de tipo pkg/feature apunten a una ruta real como ./node_modules/pkg/esm/feature.js . Además, Node.js arrojará un error si la importación se refiere a pkg/esm/feature.js que no se especifica en las exports .


Una característica adicional, aún experimental, las exportaciones condicionales proporcionan la capacidad de exportar diferentes archivos para diferentes entornos. Esto permitirá que el paquete proporcione el código CommonJS para llamar a require("pkg") y el código del módulo ES para importar a través de la import "pkg" , aunque escribir dicho paquete no está exento de otros problemas . Puede habilitar las exportaciones condicionales con el indicador " —-experimental-conditional-exports .


El rastrillo principal de los nuevos módulos.


Extensiones de archivo requeridas


Cuando use importaciones, debe especificar la extensión del archivo. Al importar un archivo de índice desde un directorio, también debe especificar completamente la ruta al archivo, es decir, "./startup/index.js".


Este comportamiento coincide con el funcionamiento de las importaciones en los navegadores cuando se accede a un servidor normal sin configuración adicional.


module.exports , exports , module.exports , __filename , __dirname


Estos valores de CommonJS no están disponibles en el contexto de los módulos ES. Sin embargo, require se puede importar al módulo ES a través de module.createRequire() . Los equivalentes __filename y __dirname se pueden obtener de import.meta.url .


Creando paquetes


Por el momento, recomendamos que los autores de paquetes utilicen módulos totalmente CommonJS o totalmente ES para sus proyectos Node.js. El grupo de trabajo de módulos para Node.js continúa buscando formas de mejorar el soporte para paquetes duales, con CommonJS para usuarios heredados y módulos ES para nuevos. Las exportaciones condicionales ahora son experimentales y esperamos implementar esta funcionalidad o su alternativa para fines de enero de 2020, o incluso antes.


Para obtener más información sobre esto, consulte nuestros ejemplos y recomendaciones para crear paquetes duales de módulos CommonJS / ES.


¿Qué pasará después?


Cargadores El trabajo continúa en la API para escribir cargadores personalizados, para implementar la transpilación de módulos en tiempo de ejecución, anular rutas de importación (paquetes o archivos individuales) y también instrumentación de código. La API experimental, disponible bajo el indicador " —-experimental-loader , estará sujeta a modificaciones importantes antes de que la eliminemos del indicador.


Paquetes de módulos duales CommonJS / ES. Queremos proporcionar una forma estándar de publicar un paquete que pueda usarse tanto mediante require en CommonJS como mediante import en módulos ES. Tenemos más información sobre esto en la documentación . Planeamos completar el trabajo y retirarnos de la bandera para fines de enero de 2020, si no antes.


Eso es todo! Esperamos que el soporte de ECMAScript para módulos acerque Node.js a los estándares de JavaScript y brinde nuevas características de compatibilidad en todo el ecosistema de JavaScript. El flujo de trabajo para mejorar el soporte del módulo se está haciendo públicamente aquí: https://github.com/nodejs/modules .

Source: https://habr.com/ru/post/477168/


All Articles