Import Attributes: Importando JSON e CSS Direto no JavaScript

Como a sintaxe with { type: 'json' } permite importar arquivos JSON (e, mais recentemente, CSS) diretamente em módulos ES, sem fetch nem configuração de bundler.

Importar um arquivo JSON direto em um módulo ES sempre foi um problema mal resolvido: o navegador não tem como saber, só pelo caminho, que ./config.json deve ser interpretado como dados e não como JavaScript. Os import attributes resolvem isso com uma sintaxe pequena e explícita — with { type: 'json' } — que declara o tipo do módulo importado no próprio import, sem depender de extensão de arquivo, cabeçalho HTTP ou configuração de bundler.

O problema que eles resolvem

Antes dessa sintaxe, trazer um JSON para dentro de um módulo exigia fetch e um await response.json(), mesmo quando o arquivo era estático e conhecido em tempo de build:

const resposta = await fetch('./config.json');
const config = await resposta.json();

console.log(config.apiUrl);

Funciona, mas é assíncrono só por causa da mecânica de carregamento, exige tratamento de erro de rede para um arquivo que está no mesmo projeto, e não passa pelo cache de módulos do próprio import. Tentar simplesmente fazer import config from './config.json' sem indicar o tipo gera erro, porque o especificador aponta para um arquivo que não é JavaScript.

Como funciona o with { type: 'json' }

A cláusula with depois do especificador do módulo declara um atributo obrigatório para a resolução do import. Para JSON, o runtime faz o parse do arquivo e entrega o resultado como export default:

import config from './config.json' with { type: 'json' };

console.log(config.apiUrl);

Sem o with { type: 'json' }, o navegador ou o runtime tentaria interpretar o conteúdo como JavaScript e falharia. Com o atributo, o tipo é explícito e verificado: se o arquivo não for JSON válido, ou se o servidor responder com um Content-Type incompatível, o import falha em vez de executar algo inesperado.

Import dinâmico com atributos

O import() dinâmico aceita o mesmo atributo como segundo argumento, útil quando o caminho do JSON só é conhecido em tempo de execução:

async function carregarTraducao(idioma) {
    const modulo = await import(`./i18n/${idioma}.json`, {
        with: { type: 'json' }
    });
    return modulo.default;
}

const textos = await carregarTraducao('pt-br');
console.log(textos.boasVindas);

Diferente do fetch, o resultado passa pelo cache de módulos: importar o mesmo JSON duas vezes não dispara duas requisições nem dois parses.

Reexportando um JSON de outro módulo

Como qualquer import, um JSON importado com atributo pode ser reexportado, o que é útil para centralizar configuração:

// configs.js
export { default as producao } from './config.producao.json' with { type: 'json' };
export { default as desenvolvimento } from './config.dev.json' with { type: 'json' };

CSS como módulo

A mesma sintaxe também define type: 'css', que importa uma folha de estilos como um objeto CSSStyleSheet pronto para ser usado com adoptedStyleSheets — sem precisar injetar uma tag <link> ou <style>:

import folha from './componente.css' with { type: 'css' };

document.adoptedStyleSheets = [...document.adoptedStyleSheets, folha];

O suporte a type: 'css' é mais recente e menos uniforme entre navegadores do que o de JSON, então vale conferir a compatibilidade antes de depender dele em produção.

Quando usar

Cuidados

A sintaxe atual usa a palavra-chave with; uma versão anterior, chamada import assertions, usava assert { type: 'json' } e já está obsoleta — motores modernos priorizam with, e código novo não deve mais usar assert. O atributo type é obrigatório para JSON e CSS: omiti-lo não faz o runtime "adivinhar" o tipo pela extensão do arquivo.

Compatibilidade

O suporte a with { type: 'json' } é amplo nos navegadores modernos (Chrome, Edge e Firefox recentes, Safari a partir da versão 17.2) e no Node.js a partir da versão 22, alcançando cobertura ampla desde 2025. Já type: 'css' tem suporte mais recente e vale checar caso a caso.

caniuse

Conclusão

Import attributes tornam explícito algo que antes dependia de convenção ou de um passo extra com fetch: o tipo do recurso importado. Para JSON, o ganho imediato é carregar dados estáticos direto pelo sistema de módulos, com cache e sem assincronismo desnecessário — e para CSS, abrem caminho para compartilhar folhas de estilo sem tocar no DOM manualmente.

Tecnologia:
js

Deixe seu Comentário!

Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.

Comentário
Nome
Email
lock Seu e-mail não será publicado.