Aprenda / JavaScript do zero

IntermediárioAula 12 de 1615 min0% da trilha

Módulos ES: import e export

require e import não são a mesma coisa por baixo — misturar os dois sem entender por quê é a causa do erro clássico 'Cannot use import statement outside a module'.

Todo projeto Next.js que você já usou tem arquivos se importando o tempo todo com import. Vale entender o que essa sintaxe realmente é — e por que ela não é intercambiável com o require que você às vezes vê em código Node mais antigo.

Named export vs. default export

matematica.js
export function somar(a, b) {
  return a + b;
}
export function subtrair(a, b) {
  return a - b;
}

export default function multiplicar(a, b) {
  return a * b;
}
uso.js
import multiplicar, { somar, subtrair } from "./matematica.js";
// default não usa chaves e você escolhe o nome livremente;
// named precisa das chaves e do nome exato (ou "as" pra renomear)

import { somar as soma } from "./matematica.js";

Um arquivo pode ter só um export default, mas quantos export nomeados quiser. Use default pra "a coisa principal que esse arquivo exporta"; named pra utilitários que fazem sentido em conjunto.

CommonJS vs. ES Modules — dois sistemas diferentes

CommonJS — Node clássico, sem 'type: module' no package.json
const { somar } = require("./matematica");
module.exports = { somar };
ES Modules — Node moderno com 'type: module', ou qualquer código pra navegador
import { somar } from "./matematica.js";
export { somar };

Não são dois jeitos de escrever a mesma coisa — são dois sistemas de módulo diferentes, com regras próprias. require é resolvido em tempo de execução, então pode aparecer dentro de um if ou de uma função. import é estático — analisado antes mesmo do código começar a rodar — e por isso só pode ficar no nível mais externo do arquivo.

O erro clássico

// Cannot use import statement outside a module
import { somar } from "./matematica.js";

Esse erro aparece quando o arquivo está sendo executado no modo CommonJS (o padrão do Node quando o package.json não declara "type": "module"), mas o código usa sintaxe de ES Modules. O motor lê import e não sabe interpretar aquilo naquele modo — não é um erro do seu código, é um descompasso entre a sintaxe usada e como o arquivo está sendo rodado.

Exercício

Reescreva este trecho CommonJS como ES Modules: const { formatar } = require("./utils"); module.exports = { formatar };

Quiz rápido

Qual a diferença entre export default e named export num mesmo arquivo?
Por que aparece o erro 'Cannot use import statement outside a module'?