Ao terminar esta aula, você vai conseguir
- Explicar a responsabilidade de um módulo
- Exportar e importar funções com ES Modules
- Configurar type e scripts no package.json
Um arquivo único resolve o primeiro exercício, mas logo passa a misturar regras, entrada e saída. Um módulo é uma unidade de código com uma responsabilidade e uma interface explícita. Em Node.js, você pode exportar valores de um arquivo e importá-los em outro, sem transformar tudo em variável global.
Imagine uma oficina: uma bancada mede peças, outra monta e outra confere o resultado. Cada bancada entrega algo definido à próxima. Um módulo faz essa separação no programa. O limite da comparação é importante: arquivos não são obrigatoriamente equipes isoladas; módulos ainda dependem uns dos outros, e uma divisão ruim apenas espalha a confusão.
Declare o formato do projeto
Na pasta do projeto, crie um package.json mínimo:
{
"name": "pedidos-node",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"start": "node src/app.js"
}
}O package.json descreve o pacote. private reduz o risco de publicação
acidental; type: module informa que arquivos .js usam ES Modules; e
scripts.start dá um nome estável ao comando. Depois disso, npm start executa
node src/app.js. O npm não substitui Node: ele apenas encontra e roda o script
declarado.
Exporte uma regra, importe no ponto de entrada
Crie a pasta src. Em src/pedido.js, escreva:
export function calcularTotal(itens) {
return itens.reduce((soma, item) => soma + item.preco, 0);
}
export function pedidoValido(itens) {
return Array.isArray(itens) && itens.length > 0;
}Agora crie src/app.js:
import { calcularTotal, pedidoValido } from './pedido.js';
const itens = [{ nome: 'Mouse', preco: 90 }, { nome: 'Cabo', preco: 30 }];
if (!pedidoValido(itens)) {
console.error('Pedido sem itens');
process.exitCode = 1;
} else {
console.log(`Total: R$ ${calcularTotal(itens).toFixed(2)}`);
}Rode npm start. A saída deve ser Total: R$ 120.00. pedido.js concentra
regras do domínio; app.js escolhe os dados, chama essas regras e apresenta o
resultado. A extensão .js no caminho relativo faz parte da resolução de ES
Modules no Node e não deve ser omitida nesse exemplo.
Uma interface pequena reduz acoplamento
Acoplamento é o quanto uma parte conhece detalhes de outra. Se app.js
precisasse conhecer todos os passos internos do cálculo, qualquer mudança teria
efeito espalhado. Ao importar calcularTotal, ele depende apenas do nome, dos
argumentos e do retorno da função. Isso não elimina dependências; torna o
contrato visível.
No laboratório, as funções aparecem juntas porque o sandbox executa um único
script do navegador. Não estamos simulando import nem package.json. A prática
verificável é outra: alterar a taxa afeta o cálculo, enquanto a função de
formatação continua igual. Depois você aplica a mesma separação em arquivos no
projeto Node real.
Faça também um teste de fronteira: renomeie calcularTotal apenas no módulo e
rode o projeto. O erro de importação mostra que o nome exportado pertence ao
contrato. Em seguida, atualize a importação e confirme a saída novamente. Esse
experimento curto torna a dependência visível. Se uma função só é usada dentro
de pedido.js, não a exporte por precaução; manter a superfície pública pequena
deixa menos detalhes disponíveis para acoplamento acidental.
Scripts nomeados também padronizam o trabalho da equipe. Uma pessoa não precisa memorizar em qual pasta está o ponto de entrada; ela consulta o manifesto e roda o mesmo comando. Quando você mudar a estrutura interna, ajuste o script uma vez. O nome público pode continuar estável. Essa é outra forma de contrato: detalhes do caminho ficam encapsulados pelo pacote.
Erro comum: misturar CommonJS e ES Modules
Node também suporta CommonJS, com require e module.exports. O erro aparece
quando um projeto declara type: module e o código tenta usar require como se
nada tivesse mudado. Escolha um sistema conscientemente; nesta trilha usamos
import e export. Ao copiar um exemplo antigo, confira primeiro em qual
formato ele foi escrito.
Para concluir a missão, extraia validarPedido, importe em app.js e rode
npm start. Teste uma lista preenchida e outra vazia. O programa precisa aprovar
a primeira e rejeitar a segunda sem duplicar a regra. Na próxima aula, veremos
como continuar organizado quando uma operação demora e termina no futuro.
Laboratório ao vivo
Funções separadas por responsabilidade
O sandbox usa um arquivo só. Treine funções independentes: altere a taxa e confirme que calcularTotal muda sem alterar a função que formata a saída.
Pare e pense
O que o campo type com valor module informa ao Node.js?
O campo type define como o Node interpreta arquivos .js naquele pacote. Com module, você pode usar a sintaxe import e export dos ES Modules.
Faça sem copiar
Extraia uma função validarPedido para pedido.js, importe-a em app.js e crie um script start. A missão passa quando npm start exibe um pedido válido.
Fontes para consultar
Terminou a missão?
Marque apenas quando você conseguir explicar o conceito e concluir o desafio. O progresso fica salvo somente neste navegador.
Próxima: Assincronia no Node.js: Promises, async e event loop →