O NodeJS planeja suportar módulos de importação / exportação es6 (es2015)

275

Eu tenho procurado por toda a internet sem uma resposta clara para isso.

Atualmente, o NodeJS usa apenas a sintaxe CommonJS para carregar módulos e, se você realmente deseja usar a sintaxe padrão dos módulos do ES2015, é necessário transpilar previamente ou usar um carregador de módulo externo em tempo de execução.

Atualmente, não sou muito positivo em usar um desses dois métodos. Os mantenedores do NodeJS estão planejando dar suporte aos módulos do ES2015 ou não? Eu não encontrei uma dica sobre isso.

No momento, o NodeJS 6.x afirma apoiar 96% dos recursos do ES2015, mas não há nenhuma referência a módulos ( link de suporte do NodeJS ES2105 ).

Você sabe se o NodeJS suportará esses módulos imediatamente, em um futuro próximo?

Zorgatone
fonte
2
Pesquisando em node es2015 modules, mostra o seguinte como um dos principais resultados: github.com/nodejs/node/wiki/ES6-Module-Detection-in-Node .
Felix Kling
6
Pessoalmente, votaria para encerrar esta questão como "localizada demais", mas esse motivo não existe mais. Digamos que o Node consiga implementar os módulos ES6 amanhã. Você vai excluir sua pergunta então, porque ela não é mais relevante? Ou você vai pelo menos atualizá-lo? Não acho que uma pergunta seja adequada para SO, se você já sabe que ela está desatualizada ou precisa ser atualizada "em breve". Mas isso é apenas a minha opinião e parece haver outros que pensam o contrário, o que é ok para mim :) (fwiw, por si só, a questão é, naturalmente, importante e interessante)
Felix Kling
2
Eu gostaria que houvesse um lugar no Universo Stack para perguntas como essa, no entanto. Pode não caber tecnicamente aqui, mas também não sei se concordo que seja realmente "baseado em opiniões". O OP está procurando uma resposta específica para uma pergunta específica, mas que será (em algum momento) desatualizada.
Wonko the Sane
5
Formulação alternativa desta pergunta: "Qual é o estado do suporte do node.js. para os módulos ES6?" A resposta para muitas perguntas de SO muda com o tempo à medida que a tecnologia evolui. Eu também tive problemas para encontrar a resposta até chegar aqui.
Joe Lapp
4
@FelixKling eu acho que você querendo fechar esta pergunta teria sido uma decisão muito errada, já que é um problema que 211 pessoas até agora acharam problemáticas o suficiente para votar.
Muhammad Umer

Respostas:

302

Nó 13.2.0 ou superior

O NodeJS 13.2.0 agora suporta os Módulos ES sem um sinalizador 🎉 No entanto, a implementação ainda está marcada como experimental, portanto, use na produção com cuidado.

Para habilitar o suporte ao ESM na 13.2.0, adicione o seguinte ao seu package.json:

{
  "type": "module"
}

Todos .js, .mjs(ou arquivos sem uma extensão) será tratado como ESM.

Existem várias opções diferentes da aceitaçãopackage.json total, todas detalhadas na documentação para 13.2.0 .

Nó 13.1.0 e inferior

Aqueles que ainda usam versões mais antigas do Node podem querer experimentar o carregador de módulo esm , que é uma implementação pronta para produção da ES Modules Spec for NodeJS:

node -r esm main.js

Atualizações detalhadas ...

23 de abril de 2019

Um PR chegou recentemente para alterar a maneira como os Módulos ES são detectados: https://github.com/nodejs/node/pull/26745

Ainda está atrás do --experimental-modulessinalizador, mas há grandes mudanças na maneira como os módulos podem ser carregados:

  • package.typeque pode ser um moduleoucommonjs
    • type: "commonjs":
      • .js é analisado como commonjs
      • o padrão para o ponto de entrada sem uma extensão é commonjs
    • type: "module":
      • .js é analisado como esm
      • não suporta carregar JSON ou Native Module por padrão
      • o padrão para o ponto de entrada sem uma extensão é esm
  • --type=[mode]para permitir que você defina o tipo no ponto de entrada. Substituirá package.typepelo ponto de entrada.
  • Uma nova extensão de arquivo .cjs.
    • isso é especificamente para oferecer suporte à importação de commonjs no modulemodo
    • isso é apenas no carregador esm, o carregador commonjs permanece intocado, mas a extensão funcionará no carregador antigo se você usar o caminho completo do arquivo.
  • --es-module-specifier-resolution=[type]
    • opções são explicit(padrão) enode
    • por padrão, nosso carregador não permitirá extensões opcionais na importação, o caminho para um módulo deve incluir a extensão se houver uma
    • por padrão, nosso carregador não permitirá a importação de diretórios que possuem um arquivo de índice
    • os desenvolvedores podem usar --es-module-specifier-resolution=nodepara ativar o algoritmo de resolução do especificador commonjs
    • Este não é um "recurso", mas uma implementação para experimentação. Espera-se que mude antes que o sinalizador seja removido
  • --experimental-json-loader
    • a única maneira de importar json quando "type": "module"
    • quando ativar tudo import 'thing.json', passará pelo carregador experimental independente do modo
    • com base no whatwg / html # 4315
  • Você pode usar package.mainpara definir um ponto de entrada para um módulo
    • as extensões de arquivo usadas no main serão resolvidas com base no tipo do módulo

17 de janeiro de 2019

O nó 11.6.0 ainda lista os Módulos ES como experimentais, atrás de um sinalizador.

13 de setembro de 2017

O NodeJS 8.5.0 foi lançado com suporte para arquivos mjs atrás de um sinalizador:

node --experimental-modules index.mjs

O plano para isso é remover o sinalizador da versão v10.0 LTS.

- Informações desatualizadas. Mantido aqui para fins históricos--

8 de setembro de 2017

A ramificação principal do NodeJS foi atualizada com suporte inicial para módulos ESM:
https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5

Isso deve estar disponível na última noite (isso pode ser instalado via nvm para ser executado juntamente com a instalação existente):
https://nodejs.org/download/nightly/

E ativado atrás da --experimental-modulesbandeira:

package.json

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

Então corra:

node --experimental-modules .

Fevereiro de 2017:

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

O pessoal do NodeJS decidiu que a solução menos ruim é usar a .mjsextensão do arquivo. A conclusão disso é:

Em outras palavras, dados dois arquivos foo.jse bar.mjs, using import * from 'foo'tratará foo.jscomo CommonJS enquanto import * from 'bar' tratará bar.mjscomo um módulo ES6

E quanto aos prazos ...

No momento atual, ainda existem vários problemas de especificação e implementação que precisam ocorrer no lado ES6 e na Máquina Virtual antes que o Node.js possa começar a trabalhar em uma implementação suportável dos módulos ES6. Trabalho está em andamento, mas vai levar algum tempo - Estamos navegando em torno de um ano , pelo menos .

Outubro de 2016:

Um dos desenvolvedores do Node.JS participou recentemente de uma reunião do TC-39 e escreveu um excelente artigo sobre os bloqueadores para a implementação do Node.JS:

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

A retirada básica disso é:

  • Módulos ES são analisados ​​estaticamente, CommonJS são avaliados
  • Os módulos CommonJS permitem exportações de patches de macaco, atualmente os Módulos ES não
  • É difícil detectar o que é um módulo ES e o que é CommonJS sem alguma forma de entrada do usuário, mas eles estão tentando.
  • *.mjs parece a solução mais provável, a menos que eles possam detectar com precisão um módulo ES sem a entrada do usuário

- Resposta original -

Esta tem sido uma batata quente há algum tempo. A conclusão é que sim, o Node eventualmente suportará a sintaxe do ES2015 para importar / exportar módulos - provavelmente quando a especificação para carregar módulos for finalizada e acordada.

Aqui está uma boa visão geral do que está mantendo o NodeJS. Essencialmente, eles precisam garantir que a nova especificação funcione para o Node, que é principalmente carregamento síncrono condicional e também HTML, que é basicamente assíncrono.

Ninguém sabe ao certo agora, mas imagino que o Node suporte import/exportpara carregamento estático, além do novo System.importpara carregamento dinâmico - enquanto mantém o requirecódigo legado.

Aqui estão algumas propostas sobre como o Node pode conseguir isso:

CodingIntrigue
fonte
38
Sobre .mjsextensão: We have affectionately called these “Michael Jackson Script” files in the past. Apenas no caso de você ouvir alguém falando sobre artistas pop durante o JS.
Jeewes 6/03/2017
1
Não estou vendo por que alterar a sintaxe de importação não é suficiente. Uma sintaxe para importar es (a 'correta') e outra para importar cjs? Em outras palavras, dados dois arquivos foo.js e bar.js, import * from 'foo'tratará foo.js como o CommonJS import * as bar from 'bar'tratará bar.js como um módulo ES6 Alguém pode explicar?
Corey Alix
1
A sintaxe do @CoreyAlix geralmente não será alterada para oferecer suporte a um ambiente. Afinal, isso realmente afeta apenas o Node. Além disso, a sintaxe é um pouco não intuitiva. Como acesso as exportações na sua sintaxe proposta?
CodingIntrigue
Para deixar claro, não é "minha" proposta, estou copiando o que o texto datilografado já está fazendo. Para responder sua pergunta, você acessa as exportações com "bar": bar.foobar () import {foo como Foo} de "./foo" é o mecanismo para identificar um módulo ES6. var Foo = require (“./ foo”) é o mecanismo para identificar o módulo CJS. No TypeScript, a saída do commonjs é assim: var mod1_1 = require ("./ mod1"); export.mod1 = mod1; A saída do ES6 é assim: import {mod1} de "./mod1"; exportar {mod1}
Corey Alix
1
Eu seria realmente interessante em uma atualização do Nó 10 para esta resposta. O recurso fez o corte ou ainda está atrás de uma bandeira?
Dcorking 19/07/19