Módulos ES (import/export)
Nesta aula, você aprenderá sobre Módulos ES em JavaScript, incluindo export nomeado e default, import e como usá-los no browser e no Node.js. Vamos explorar a sintaxe, boas práticas e diferenças entre os ambientes, com exemplos práticos e exercícios para fixar o conteúdo.
Os Módulos ES (ECMAScript Modules) são uma forma nativa de organizar e compartilhar código em JavaScript. Antes deles, o código era frequentemente dividido em múltiplos arquivos usando scripts comuns, mas isso gerava problemas de escopo global e dependências complexas. Com os módulos, cada arquivo é tratado como um módulo independente, que pode exportar e importar funcionalidades de outros módulos de forma explícita e eficiente.
Nesta aula, vamos mergulhar nas duas principais formas de exportação (nomeada e default), na sintaxe de importação e nas particularidades de uso no browser e no Node.js, que hoje suporta módulos ES nativamente. Vamos aprender também boas práticas para escrever código modular e manutenível.
export nomeado e default
O export é a palavra-chave que torna uma funcionalidade disponível para outros módulos. Existem duas maneiras principais de exportar: export nomeado e export default.
O export nomeado permite exportar múltiplas variáveis, funções ou classes de um mesmo módulo, cada uma com um nome específico. Isso é útil quando você quer expor várias funcionalidades relacionadas. O export default é usado para exportar um único valor principal do módulo, que pode ser uma função, classe ou objeto. Cada módulo pode ter apenas um export default.
Vamos ver exemplos de cada um:
// arquivo: utils.js
// Export nomeado
export function soma(a, b) {
return a + b;
}
export const PI = 3.14159;
// Export default (pode ser uma função, classe, objeto, etc.)
export default function multiplica(a, b) {
return a * b;
}No exemplo acima, temos dois exports nomeados (soma e PI) e um export default (multiplica). Você pode misturá-los no mesmo módulo, mas lembre-se: apenas um default.
Uma alternativa é declarar as funcionalidades e exportá-las no final, o que pode melhorar a legibilidade:
// arquivo: utils.js
function soma(a, b) {
return a + b;
}
const PI = 3.14159;
function multiplica(a, b) {
return a * b;
}
export { soma, PI };
export default multiplica;Outra sintaxe comum é usar export { x as y } para renomear no momento da exportação, e também é possível exportar listas de variáveis.
import
O import é usado para trazer funcionalidades de outros módulos. A sintaxe varia conforme o tipo de exportação: nomeada ou default.
Para imports nomeados, usamos chaves { } e podemos renomear com as. Para o default, não usamos chaves. Também é possível importar tudo com import * as nome.
Veja como importar do módulo utils.js:
// arquivo: main.js
import multiplica, { soma, PI as pi } from './utils.js';
console.log(soma(2, 3)); // 5
console.log(pi); // 3.14159
console.log(multiplica(2, 3)); // 6No código acima, importamos o default (multiplica) e os nomeados (soma e PI renomeado para pi). A ordem do default pode ser qualquer, mas é comum colocá-lo primeiro.
Se quisermos importar tudo como um objeto:
import * as utils from './utils.js';
console.log(utils.soma(2, 3)); // 5
console.log(utils.PI); // 3.14159
console.log(utils.default(2, 3)); // 6Note que o default fica acessível como utils.default.
Importações são hoisted, ou seja, são executadas antes do resto do código, mas é boa prática colocá-las no topo do arquivo.
Módulos no browser e no Node
No browser, os módulos ES são suportados nativamente em todos os navegadores modernos. Para usá-los, você precisa incluir o script com type="module" no HTML:
<script type="module" src="main.js"></script>Os módulos no browser são carregados de forma assíncrona e têm escopo próprio. Eles são sujeitos a CORS, então precisam ser servidos por um servidor HTTP (não podem ser abertos como arquivo local). Os imports devem especificar a extensão do arquivo (ex.: ./utils.js).
No Node.js, o suporte a módulos ES foi adicionado na versão 12 (experimental) e estável a partir da versão 14. Para usar, você deve definir "type": "module" no package.json ou usar a extensão .mjs nos arquivos. Exemplo de package.json:
{
"type": "module"
}No Node, os imports também precisam da extensão do arquivo (ex.: ./utils.js). A partir do Node 20, é possível importar módulos ES de forma síncrona e também usar require() em alguns casos, mas a recomendação é usar imports ES.
Exemplo de uso no Node:
// arquivo: utils.js
export function soma(a, b) {
return a + b;
}
// arquivo: main.js
import { soma } from './utils.js';
console.log(soma(2, 3)); // 5Diferenças importantes: no browser, os módulos são sempre estritos ("use strict" automático) e têm escopo de módulo; no Node, o comportamento é semelhante, mas há diferenças no carregamento de módulos CommonJS (require) e ES.
Boas práticas e observações finais
Para escrever módulos limpos e eficientes, considere:
- Use exports nomeados para múltiplas funcionalidades e default apenas para o principal.
- Prefira imports explícitos em vez de
import *, para melhorar a rastreabilidade e o tree-shaking. - Mantenha os módulos pequenos e com responsabilidade única.
- Evite circular dependencies, que podem causar erros.
- No Node, tenha cuidado com a mistura de CommonJS e ES Modules; prefira um padrão consistente.
Esses conceitos são fundamentais para construir aplicações modernas e escaláveis em JavaScript, tanto no front-end quanto no back-end.
Referências
- MDN: Módulos JavaScript
- MDN: export
- MDN: import
- Node.js: Módulos ES
- MDN: Módulos em ambientes de navegador
- MDN: Sintaxe de import
Exercícios
Crie um módulo chamado
math.jsque exporte uma funçãosoma(nomeada) e uma funçãomultiplica(default). Depois, crie um arquivomain.jsque importe ambas e as utilize.✓ Resposta:// math.js export function soma(a, b) { return a + b; } export default function multiplica(a, b) { return a * b; } // main.js import multiplica, { soma } from './math.js'; console.log(soma(2, 3)); // 5 console.log(multiplica(2, 3)); // 6Explique a diferença entre export nomeado e export default, e dê um exemplo de quando usar cada um.
✓ Resposta: O export nomeado permite exportar múltiplas funcionalidades com nomes específicos, facilitando a importação seletiva. O export default exporta um único valor principal, que pode ser importado sem chaves. Use nomeados para bibliotecas de utilitários, e default para o componente principal de um módulo (ex.: uma classe ou função principal).Como você importaria todas as exportações de um módulo como um objeto? Dê um exemplo com o módulo
utils.jsque tem as funçõesaeb.✓ Resposta:// utils.js export function a() { return 'a'; } export function b() { return 'b'; } // main.js import * as utils from './utils.js'; console.log(utils.a()); // 'a' console.log(utils.b()); // 'b'No browser, qual é a diferença crucial ao usar módulos em relação a scripts tradicionais? Cite duas características.
✓ Resposta: 1) Os módulos têm escopo próprio, evitando poluição do escopo global. 2) São carregados de forma assíncrona e diferida, não bloqueando o carregamento da página. Além disso, precisam ser servidos por um servidor HTTP devido a CORS.No Node.js, como você configura um projeto para usar módulos ES? Liste os passos e dê um exemplo de
package.json.✓ Resposta: Passos: 1) Crie um arquivopackage.jsonno diretório do projeto. 2) Adicione"type": "module". 3) Use extensão.jsou.mjspara os arquivos. Exemplo depackage.json:
Depois, escreva seus módulos usando{ "type": "module" }import/export.