O conceito de módulos vem do paradigma de programação modular. Este paradigma propõe que o software seja composto de componentes separados e intercambiáveis chamados “módulos” dividindo as funções do programa em arquivos autônomos que podem funcionar separadamente ou acoplados em um aplicativo.
Um módulo é um arquivo autônomo que encapsula o código para implementar determinadas funcionalidades e promover a reutilização e a organização.
Aqui você abordará os sistemas de módulo usados em aplicativos JavaScript, incluindo o padrão de módulo, o sistema de módulo CommonJS usado na maioria dos aplicativos Node.js e o sistema de módulo ES6.
O padrão do módulo
Antes da introdução dos módulos JavaScript nativos, o padrão de design do módulo era usado como um sistema de módulo para definir variáveis e funções em um único arquivo.
Isso foi implementado usando expressões de função invocadas imediatamente, popularmente conhecidas como IIFEs. Um IIFE é uma função não reutilizável que é executada assim que é criada.
Aqui está a estrutura básica de um IIFE:
(função () {
//código aqui
})();(() => {
//código aqui
})();
(assíncrono () => {
//código aqui
})();
O bloco de código acima descreve IIFEs usados em três contextos diferentes.
IIFEs foram usados porque as variáveis declaradas dentro de uma função têm escopo para a função, tornando-as apenas acessíveis dentro da função e porque as funções permitem que você retorne dados (tornando-os publicamente acessível).
Por exemplo:
const foo = (função () {
const digaNome = (nome) => {
console.registro('Ei, meu nome é ${nome}`);
};
//Expondo as variáveis
retornar {
callSayName: (nome) => digaNome (nome),
};
})();
//Acessando métodos expostos
foo.callSayName("Bar");
O bloco de código acima é um exemplo de como os módulos foram criados antes da introdução dos módulos JavaScript nativos.
O bloco de código acima contém um IIFE. O IIFE contém uma função que torna acessível retornando-a. Todas as variáveis declaradas no IIFE são protegidas do escopo global. Assim, o método (digaNome) só é acessível por meio da função pública, callSayName.
Observe que o IIFE é salvo em uma variável, foo. Isso ocorre porque, sem uma variável apontando para sua localização na memória, as variáveis ficarão inacessíveis após a execução do script. Este padrão é possível devido Fechos de JavaScript.
O Sistema de Módulos CommonJS
O sistema de módulos CommonJS é um formato de módulo definido pelo grupo CommonJS para resolver problemas de escopo do JavaScript executando cada módulo em seu namespace.
O sistema de módulo CommonJS funciona forçando os módulos a exportar explicitamente as variáveis que desejam expor a outros módulos.
Este sistema modular foi criado para JavaScript do lado do servidor (Node.js) e, como tal, não é suportado por padrão nos navegadores.
Para implementar os módulos CommonJS em seu projeto, você deve primeiro inicializar o NPM em seu aplicativo executando:
npm init -y
As variáveis exportadas seguindo o sistema de módulos CommonJS podem ser importadas da seguinte forma:
//randomModule.js
//pacote instalado
const installImport = exigir("nome do pacote");
//módulo local
const localImport = exigir("/path-to-module");
Os módulos são importados no CommonJS usando o exigir instrução, que lê um arquivo JavaScript, executa o arquivo lido e retorna o exporta objeto. O exporta O objeto contém todas as exportações disponíveis no módulo.
Você pode exportar uma variável seguindo o sistema de módulo CommonJS usando exportações nomeadas ou exportações padrão.
Exportações nomeadas
As exportações nomeadas são exportações identificadas pelos nomes aos quais foram designadas. As exportações nomeadas permitem várias exportações por módulo, ao contrário das exportações padrão.
Por exemplo:
//main.js
exports.myExport = função () {
console.log("Este é um exemplo de um nomeado exportar");
};
exports.anotherExport = função () {
console.log("Este é outro exemplo de um nomeado exportar");
};
No bloco de código acima, você está exportando duas funções nomeadas (myExport e outroExportar) anexando-os ao exporta objeto.
Da mesma forma, você pode exportar as funções da seguinte forma:
const minhaExportação = função () {
console.log("Este é um exemplo de um nomeado exportar");
};
const outraExportação = função () {
console.log("Este é outro exemplo de um nomeado exportar");
};
módulo.exporta = {
minhaExportação,
outroExportar,
};
No bloco de código acima, você define o exporta objeto para as funções nomeadas. Você só pode atribuir o exporta objeto a um novo objeto através do módulo objeto.
Seu código lançaria um erro se você tentasse fazer desta maneira:
//Maneira errada
exporta = {
minhaExportação,
outroExportar,
};
Há duas maneiras de importar exportações nomeadas:
1. Importe todas as exportações como um único objeto e acesse-as separadamente usando a notação de ponto.
Por exemplo:
//otherModule.js
const foo = exigir("./principal");
foo.minhaExportação();
foo.anotherExport();
2. Desestruturar as exportações do exporta objeto.
Por exemplo:
//otherModule.js
const { minhaExportação, outraExportação } = exigir("./principal");
minhaExport();
outroExport();
Uma coisa é comum em todos os métodos de importação, eles devem ser importados usando os mesmos nomes com os quais foram exportados.
Exportações Padrão
Uma exportação padrão é uma exportação identificada por qualquer nome de sua escolha. Você só pode ter uma exportação padrão por módulo.
Por exemplo:
//main.js
aulaFoo{
bar() {
console.log("Este é um exemplo de a padrãoexportar");
}
}
módulo.exporta = Foo;
No bloco de código acima, você está exportando uma classe (Foo) reatribuindo o exporta opor-se a isso.
A importação de exportações padrão é semelhante à importação de exportações nomeadas, exceto que você pode usar qualquer nome de sua escolha para importá-las.
Por exemplo:
//otherModule.js
const Barra = exigir("./principal");
const objeto = novo Bar();
objeto.bar();
No bloco de código acima, a exportação padrão foi nomeada Bar, embora você possa usar qualquer nome de sua escolha.
O sistema de módulos ES6
O sistema de módulos ECMAScript Harmony, popularmente conhecido como módulos ES6, é o sistema de módulos JavaScript oficial.
Os módulos ES6 são suportados por navegadores e servidores, embora você exija um pouco de configuração antes de usá-los.
Nos navegadores, você deve especificar o tipo como módulo na tag de importação do script.
Igual a:
//index.html
<script origem="./app.js" tipo="módulo"></script>
No Node.js, você deve definir tipo para módulo na tua pacote.json arquivo.
Igual a:
//package.json
"tipo":"módulo"
Você também pode exportar variáveis usando o sistema de módulo ES6 usando exportações nomeadas ou exportações padrão.
Exportações nomeadas
Semelhante às importações nomeadas em módulos CommonJS, elas são identificadas pelos nomes aos quais foram atribuídas e permitem várias exportações por módulo.
Por exemplo:
//main.js
exportarconst minhaExportação = função () {
console.log("Este é um exemplo de um nomeado exportar");
};
exportarconst outraExportação = função () {
console.log("Este é outro exemplo de um nomeado exportar");
};
No sistema de módulo ES6, as exportações nomeadas são exportadas prefixando a variável com o exportar palavra-chave.
As exportações nomeadas podem ser importadas para outro módulo no ES6 da mesma forma que o CommonJS:
- Desestruturar as exportações necessárias do exporta objeto.
- Importar todas as exportações como um único objeto e acessá-las separadamente usando a notação de ponto.
Aqui está um exemplo de desestruturação:
//otherModule.js
importar { minhaExportação, outraExportação } de "./main.js";
minhaexport()
outroExport()
Aqui está um exemplo de importação de todo o objeto:
importar * como foo de './main.js'
foo.minhaExportação()
foo.anotherExport()
No bloco de código acima, o asterisco (*) significa “todos”. O como palavra-chave atribui o exporta object para a string que o segue, neste caso, foo.
Exportações Padrão
Semelhante às exportações padrão no CommonJS, elas são identificadas por qualquer nome de sua escolha e você pode ter apenas uma exportação padrão por módulo.
Por exemplo:
//main.js
aulaFoo{
bar() {
console.log("Este é um exemplo de a padrãoexportar");
}
}
exportarpadrão Foo;
As exportações padrão são criadas adicionando o padrão palavra-chave após o exportar palavra-chave, seguida do nome da exportação.
A importação de exportações padrão é semelhante à importação de exportações nomeadas, exceto que você pode usar qualquer nome de sua escolha para importá-las.
Por exemplo:
//otherModule.js
importar Bar de "./main.js";
Exportações mistas
O padrão do módulo ES6 permite que você tenha exportações padrão e exportações nomeadas em um módulo, ao contrário do CommonJS.
Por exemplo:
//main.js
exportarconst minhaExportação = função () {
console.log("Este é outro exemplo de um nomeado exportar");
};
aulaFoo{
bar() {
console.log("Este é um exemplo de a padrãoexportar");
}
}
exportarpadrão Foo;
Importância dos Módulos
Dividir seu código em módulos não apenas os torna mais fáceis de ler, mas também os torna mais reutilizáveis e também de fácil manutenção. Os módulos em JavaScript também tornam seu código menos sujeito a erros, pois todos os módulos são executados em modo estrito por padrão.