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
importde módulo ES. - No Node.js, defina
"type": "module"nopackage.jsonou use a extensão de arquivo.mjspara 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
transformIgnorePatternspara 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:
| Sistema | Sintaxe | Padrão em |
|---|---|---|
| CommonJS (CJS) | require() | Node.js (legado) |
| ES Modules (ESM) | import | Navegadores, 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 usandorequire(),module.exportsou__dirnamequebrará 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.
Discover how at OpenReplay.com.
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 seupackage.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.