O Node.js. 13.2.0 vem com suporte ao ECMAScript para módulos conhecidos por sua sintaxe de importação e exportação. Anteriormente, essa funcionalidade estava atrás do --experimental-modules
, que não é mais necessário. No entanto, a implementação ainda é experimental e está sujeita a alterações.
De um tradutor: esse recurso aguardado finalmente nos permitirá usar a sintaxe modular padrão já disponível em navegadores modernos e agora também no Node.js sem sinalizadores e transpilers
Ativação
O Node.js processará o código como módulos ES nos seguintes casos:
- Arquivos com a extensão
.mjs
- Arquivos com a extensão
.js
ou sem a extensão, desde que o package.json
mais próximo contenha o valor "type": "module"
- Código passado pelo argumento
—-eval
ou STDIN, junto com o sinalizador —-input-type=module
Em todos os outros casos, o código será considerado CommonJS. Isso se aplica aos arquivos .js
sem "type": "module"
no package.json
mais próximo e ao código passado pela linha de comando sem especificar --input-type
. Isso é feito para manter a compatibilidade com versões anteriores. No entanto, como agora temos dois tipos de módulos, CommonJS e ES, será melhor especificar explicitamente o tipo de módulos.
Você pode marcar explicitamente seu código como CommonJS com os seguintes recursos:
- Arquivos com a extensão
.cjs
- Arquivos com a extensão
.js
ou sem extensão, desde que o package.json
pai mais package.json
contenha o valor "type": "“commonjs”"
- Código passado pelo argumento
--eval
ou STDIN com o sinalizador explícito --input-type=commonjs
Para saber mais sobre esses recursos, consulte as seções de documentação "Escopo do pacote e extensões de arquivo" e --input-type
Importação e exportação de sintaxe
No contexto do módulo ES, você pode usar a import
, apontando para outros arquivos Javascript. Eles podem ser especificados em um dos seguintes formatos:
- URL relativo:
"./file.mjs"
file://
c da URL absoluta file://
, por exemplo, "file:///opt/app/file.mjs"
- Nome do pacote:
"es-module-package"
- O caminho para o arquivo dentro do pacote:
"es-module-package/lib/file.mjs"
Nas importações, você pode usar os valores padrão ( import _ from "es-module-package"
) e nomeados ( import { shuffle } from "es-module-package"
), além de importar tudo como um espaço para nome ( import * as fs from "fs"
). Todos os pacotes internos do Node.js., como fs
ou path
, suportam todos os três tipos de importações.
As importações que apontam para o código CommonJS (ou seja, todo o JavaScript atual gravado para o Node.js. require
e module.exports
) podem usar apenas a opção padrão ( import _ from "commonjs-package"
).
A importação de outros formatos de arquivo, como JSON e WASM, permanece experimental e requer os sinalizadores --experimental-json-modules
e --experimental-wasm-modules
respectivamente. No entanto, você pode fazer o download desses arquivos usando a API module.createRequire
, que está disponível sem sinalizadores adicionais.
Nos seus módulos ES, você pode usar a palavra-chave export para exportar valores padrão e nomeados.
Expressões dinâmicas com import()
podem ser usadas para carregar módulos ES a partir do código CommonJS ou ES. Observe que import()
não retorna um módulo, mas sua promessa (Promise).
import.meta.url
está disponível nos módulos, que contém a URL absoluta do módulo ES atual.
Arquivos e o novo campo "type" em package.json
Adicione "type": "module"
ao package.json do seu projeto e o Node.js começará a perceber todos os arquivos .js
do seu projeto como módulos ES.
Se alguns arquivos do seu projeto ainda usarem o CommonJS e você não puder migrar o projeto inteiro de uma só vez, poderá usar a extensão .cjs
para esse código ou colocá-lo em um diretório separado e adicionar package.json
contendo o { "type": "commonjs" }
, que informa ao Node.js que ele deve ser tratado como CommonJS.
Para cada arquivo baixado, o Node.js examinará o package.json
no diretório que o contém, um nível acima e assim por diante até atingir o diretório raiz. Esse mecanismo é semelhante ao modo como o Babel .babelrc
arquivos Babel .babelrc
. Essa abordagem permite que o Node.js. use o package.json
como fonte de vários metadados sobre o pacote e a configuração, semelhante à forma como ele já funciona no Babel e em outras ferramentas.
Recomendamos que todos os desenvolvedores de pacotes especifiquem um campo de type
, mesmo se commonjs
estiver escrito commonjs
.
Os pontos de entrada do pacote e o campo "exportações" em package.json
Agora, temos dois campos para especificar o ponto de entrada no pacote: main
e exports
. O campo main
é suportado por todas as versões do Node.js, mas seus recursos são limitados: com ele você pode definir apenas um ponto de entrada principal no pacote. O novo campo de exports
também permite definir o ponto de entrada principal, bem como caminhos adicionais. Isso fornece encapsulamento adicional para pacotes em que apenas os caminhos de exports
explícitos estão disponíveis para importação de fora do pacote. exports
se aplicam a ambos os tipos de módulos, CommonJS e ES, independentemente de serem utilizados por meio de require
ou import
.
Essa funcionalidade permitirá que as importações do tipo pkg/feature
aponte para um caminho real como ./node_modules/pkg/esm/feature.js
. Além disso, o Node.js lançará um erro se a importação se referir ao pkg/esm/feature.js
que não está especificado nas exports
.
Um recurso adicional, ainda experimental, de exportações condicionais fornece a capacidade de exportar arquivos diferentes para diferentes ambientes. Isso permitirá que o pacote forneça o código CommonJS para chamar require("pkg")
e o código do módulo ES a ser importado através da import "pkg"
, embora a gravação desse pacote não ocorra sem outros problemas . Você pode habilitar exportações condicionais com o —-experimental-conditional-exports
.
O rake principal dos novos módulos
Extensões de arquivo necessárias
Ao usar importações, você deve especificar a extensão do arquivo. Ao importar um arquivo de índice de um diretório, você também deve especificar completamente o caminho para o arquivo, ou seja, "./startup/index.js".
Esse comportamento coincide com o modo como as importações funcionam nos navegadores ao acessar um servidor regular sem configuração adicional.
module.exports
, exports
, module.exports
, __filename
, __dirname
Esses valores do CommonJS não estão disponíveis no contexto dos módulos ES. No entanto, o require
pode ser importado para o módulo ES através de module.createRequire()
. Os equivalentes __filename
e __dirname
podem ser obtidos em import.meta.url
.
Criando pacotes
No momento, recomendamos que os autores do pacote usem módulos CommonJS ou ES totalmente para seus projetos Node.js. O grupo de trabalho do módulo para Node.js continua procurando maneiras de melhorar o suporte para pacotes duplos, com o CommonJS para usuários herdados e os módulos ES para novos. As exportações condicionais agora são experimentais e esperamos lançar essa funcionalidade ou sua alternativa até o final de janeiro de 2020, ou mesmo antes.
Para saber mais sobre isso, consulte nossos exemplos e recomendações para a criação de dois pacotes CommonJS / ES Module.
O que acontecerá a seguir
Carregadores. O trabalho continua na API para gravar carregadores personalizados, implementar a transpiração do módulo em tempo de execução, redefinir os caminhos de importação (pacotes ou arquivos individuais) e instrumentar o código. A API experimental, acessível sob o —-experimental-loader
, estará sujeita a alterações significativas antes de removê-lo do sinalizador.
Pacotes de módulos CommonJS / ES duplos. Queremos fornecer uma maneira padrão de publicar um pacote que pode ser usado tanto através do require
no CommonJS quanto da import
nos módulos ES. Temos mais informações sobre isso na documentação . Planejamos concluir o trabalho e retirar a bandeira até o final de janeiro de 2020, se não antes.
Isso é tudo! Esperamos que o suporte do ECMAScript aos módulos aproxime o Node.js dos padrões do JavaScript e traga novos recursos para compatibilidade em todo o ecossistema do JavaScript. O fluxo de trabalho para melhorar o suporte ao módulo está sendo realizado publicamente aqui: https://github.com/nodejs/modules .