Back

Como Corrigir 'Cannot use import statement outside a module'

Como Corrigir 'Cannot use import statement outside a module'

Você escreve uma declaração import limpa, executa seu código e imediatamente se depara com isto:

SyntaxError: Cannot use import statement outside a module

Este erro de módulos ES do JavaScript é uma das fontes mais comuns de confusão para desenvolvedores trabalhando com Node.js, navegadores e ambientes de teste. A correção nem sempre é a mesma — e aplicar a errada piora as coisas. Aqui está como diagnosticar sua situação e resolvê-la corretamente.

Pontos-Chave

  • Este erro é uma incompatibilidade de sistema de módulos, não um erro de sintaxe — seu runtime esperava CommonJS mas encontrou a sintaxe import de módulo ES.
  • No Node.js, defina "type": "module" no package.json ou use a extensão de arquivo .mjs para optar pelo ESM.
  • Em navegadores, adicione type="module" à sua tag <script> para que o motor trate o arquivo como um módulo ES.
  • No Jest, configure o Babel para transformar ESM em CommonJS, e ajuste transformIgnorePatterns para pacotes de terceiros que usam apenas ESM.
  • Sempre diagnostique seu ambiente primeiro — Node.js, navegador ou test runner — antes de aplicar uma correção.

Por Que Este Erro Acontece

O erro significa que seu runtime encontrou sintaxe de módulo ES (import) mas esperava outra coisa — geralmente CommonJS (require). É uma incompatibilidade de sistema de módulos, não um erro de sintaxe no seu código.

JavaScript tem dois sistemas de módulos:

SistemaSintaxePadrão em
CommonJS (CJS)require()Node.js (legado)
ES Modules (ESM)importNavegadores, Node.js moderno

O runtime decide qual sistema usar com base na configuração — não no código em si. É por isso que a mesma declaração import funciona em um projeto e falha em outro.

Como Corrigir o Erro Import Statement Outside Module no Node.js

O Node.js trata arquivos .js como CommonJS a menos que "type": "module" esteja definido no package.json. Para usar import, você precisa explicitamente optar pelo ESM.

Opção 1: Definir "type": "module" no package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module"
}

Isso informa ao Node.js para tratar todos os arquivos .js no projeto como módulos ES. Consulte a documentação oficial de módulos ES do Node.js para detalhes sobre como o Node determina o tipo de módulo.

Opção 2: Usar a extensão de arquivo .mjs

Renomeie seu arquivo de app.js para app.mjs. O Node.js sempre trata arquivos .mjs como ESM, independentemente do package.json.

Opção 3: Usar .cjs para arquivos CommonJS

Se seu projeto usa "type": "module" mas um arquivo precisa de require(), dê a ele uma extensão .cjs.

Importante: Não adicione simplesmente "type": "module" sem verificar seus outros arquivos. Qualquer arquivo usando require(), module.exports ou __dirname quebrará sob ESM.

Corrigindo o Erro em JavaScript no Navegador

Em navegadores, import estático só funciona dentro de um script de módulo. Se sua tag <script> não declarar type="module", o navegador a trata como um script clássico e rejeita a sintaxe import.

<!-- Isso gerará o erro -->
<script src="app.js"></script>

<!-- Isso funciona -->
<script type="module" src="app.js"></script>

Este comportamento faz parte da especificação padrão de módulos JavaScript implementada por navegadores modernos.

Note que scripts de módulo são com escopo — variáveis declaradas dentro de um não estão disponíveis globalmente. É por isso que você pode adicionar type="module" e então ver um ReferenceError para uma variável que esperava ser global. A solução é exportar e importar valores explicitamente em vez de depender do escopo global.

Corrigindo o Erro no Jest e Outros Ambientes de Teste

O Jest executa no Node.js e tradicionalmente usa CommonJS por padrão, mesmo se seu código-fonte usa ESM. Esta é uma fonte comum do erro “cannot use import statement outside a module” em suítes de teste.

Uma abordagem é configurar o Babel para transformar ESM em CommonJS durante os testes:

// babel.config.js
module.exports = {
  presets: ['@babel/preset-env'],
}

Alternativamente, o Jest pode ser configurado para executar testes em modo ESM nativo se seu projeto já usa módulos ES. Consulte a documentação de Módulos ECMAScript do Jest para detalhes.

Se um pacote de terceiros (como swiper, lodash-es ou bibliotecas similares que usam apenas ESM) está causando o erro, você precisa informar ao Jest para transformá-lo em vez de ignorá-lo:

// jest.config.js
module.exports = {
  transformIgnorePatterns: [
    '/node_modules/(?!(swiper|ssr-window|dom7)/)',
  ],
}

O insight chave: transformIgnorePatterns usa um negative lookahead. Você está dizendo “ignore tudo em node_modules exceto estes pacotes.” Listá-los em entradas de array separadas não funcionará — eles devem ser combinados em um único padrão regex com |.

Configuração do TypeScript

Se você está usando TypeScript, verifique seu tsconfig.json. O campo module controla qual sintaxe de módulo o TypeScript emite em sua saída compilada:

{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ESNext"
  }
}

Definir module como CommonJS enquanto escreve declarações import é TypeScript válido — o compilador transformará import em require() na saída. No entanto, definir module como ESNext enquanto executa a saída em um ambiente Node.js CommonJS (sem "type": "module" no package.json) acionará o erro em tempo de execução. Certifique-se de que a configuração de módulo do seu tsconfig.json corresponda ao que seu runtime realmente espera.

Diagnostique Antes de Corrigir

O mesmo erro aparece em diferentes ambientes por diferentes razões. Antes de aplicar qualquer correção, pergunte:

  • Onde o erro está ocorrendo — Node.js, navegador ou test runner?
  • O que diz o campo "type" do seu package.json?
  • Você está usando um bundler ou executando arquivos diretamente?

Responder essas três perguntas aponta para a solução certa toda vez.

Perguntas Frequentes

Sim, mas você precisa usar extensões de arquivo para distingui-los. Arquivos com extensão .mjs são sempre tratados como módulos ES, e arquivos com extensão .cjs são sempre tratados como CommonJS, independentemente do campo type no package.json. Isso permite usar ambos os sistemas lado a lado em um único projeto.

Não. Cada pacote em node_modules tem seu próprio package.json, então seu campo type só se aplica aos arquivos do seu projeto. As dependências definem seu próprio sistema de módulos independentemente. O erro geralmente vem dos seus próprios arquivos ou de importar uma dependência que usa apenas ESM em um contexto CommonJS sem a transformação adequada.

Bundlers como Webpack e Vite processam declarações import durante a etapa de build e produzem um único arquivo de saída. Eles resolvem a sintaxe de módulo antes que o runtime a veja. Quando você executa arquivos diretamente no Node.js ou em um navegador sem um bundler, o próprio runtime deve entender o formato do módulo, e é onde incompatibilidades causam este erro.

Essas globais do CommonJS não estão disponíveis em módulos ES. Em vez disso, você pode reconstruí-las usando import.meta.url. Por exemplo, use new URL(import.meta.url).pathname para obter o caminho do arquivo, ou combine-o com o módulo path e fileURLToPath do módulo url para replicar o comportamento de __dirname.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay