Back

Importación de JSON en módulos ES (sin Fetch, sin bundler)

Importación de JSON en módulos ES (sin Fetch, sin bundler)

Si alguna vez has intentado usar import config from './config.json' en un proyecto de módulos ES plano y te has topado con un muro, no estás solo. Durante años, importar JSON sin un bundler significaba recurrir a fetch() o convertir tus datos a un archivo JavaScript. Esa era de soluciones alternativas ha terminado.

A partir de 2025, los atributos de importación son compatibles de forma generalizada en navegadores modernos. Ahora puedes realizar una importación nativa de módulos JSON en JavaScript sin necesidad de herramientas de compilación.

Puntos clave

  • Usa with { type: 'json' } para importar JSON de forma nativa en módulos ES — sin necesidad de bundler o fetch().
  • El atributo type es obligatorio por seguridad: garantiza que el runtime valide el tipo MIME antes de procesar el archivo.
  • Los módulos JSON solo exponen una exportación por defecto. Desestructura a partir de ella después de la importación.
  • Tus archivos JSON deben servirse por HTTP con el encabezado correcto Content-Type: application/json.

La sintaxis moderna: atributos de importación

La sintaxis actual utiliza la palabra clave with para declarar el tipo de módulo:

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

console.log(config.apiUrl)

Para carga dinámica:

// Dynamic import
const { default: config } = await import('./config.json', {
  with: { type: 'json' }
})

Nota: La sintaxis antigua assert { type: 'json' } (compatible en Chrome 91–122) ahora está deprecada. Usa siempre with.

Por qué el atributo type: 'json' es obligatorio

El atributo with { type: 'json' } no es decoración opcional. Cumple un propósito de seguridad específico: obliga al navegador o runtime a validar el tipo MIME de la respuesta como application/json antes de procesar cualquier cosa.

Sin él, un servidor podría devolver JavaScript disfrazado como un archivo JSON, y el motor no tendría forma de hacer cumplir la distinción. El atributo type previene esto.

Los módulos JSON solo tienen una exportación por defecto

Algo que confunde a los desarrolladores: los módulos JSON no admiten exportaciones nombradas. El objeto JSON completo llega como la exportación por defecto.

import data from './data.json' with { type: 'json' }

// ✅ Correcto
const { users, settings } = data

// ❌ Esto no funcionará
import { users } from './data.json' with { type: 'json' }

Desestructura a partir de la exportación por defecto después de la importación.

Compatibilidad con navegadores y Node.js

EntornoVersión mínima
Chrome123+
Firefox138+
Safari17.2+
Node.jsLTS actual y superior

Todas estas versiones están ahora ampliamente desplegadas. Si tu objetivo son navegadores modernos y versiones actuales de Node.js, no necesitas un bundler ni una llamada fetch() para cargar JSON.

Nota: Las versiones anteriores de Node.js proporcionaban módulos JSON detrás de flags experimentales. El soporte de módulos JSON con atributos de importación ahora es estable en las versiones actuales de Node.js. Consulta la documentación ESM de Node.js para detalles exactos de versión.

Restricciones prácticas que debes conocer antes de implementar

Necesitas un servidor HTTP. Las importaciones de módulos—incluyendo módulos JSON—generalmente no funcionan al cargar páginas directamente mediante file://. Los navegadores aplican reglas de seguridad estrictas a la carga de módulos. Usa un servidor de desarrollo local como Vite, serve, o cualquier servidor de archivos estáticos.

Tu archivo JSON debe servirse con el tipo MIME correcto. El servidor necesita devolver Content-Type: application/json. La mayoría de los servidores estáticos manejan esto automáticamente para archivos .json, pero verifica si estás usando un servidor personalizado o configuración de CDN.

El JSON debe ser válido. No hay recuperación de errores a nivel de importación. Un error de sintaxis en tu archivo JSON causará que el módulo falle completamente al cargarse. Valida tu JSON antes de implementar.

Un ejemplo del mundo real

// config.json
{
  "apiUrl": "https://api.example.com",
  "timeout": 5000,
  "features": {
    "darkMode": true
  }
}
// app.js
import config from './config.json' with { type: 'json' }

const { apiUrl, timeout, features } = config

if (!apiUrl || typeof timeout !== 'number') {
  throw new Error('Invalid configuration')
}

Este patrón funciona de manera limpia para archivos de configuración, feature flags, cadenas de i18n, o cualquier dato estructurado estático que tu aplicación necesite al inicio.

Conclusión

Los atributos de importación te dan una forma limpia y nativa de importar JSON en módulos ES sin fetch(), sin un bundler y sin soluciones alternativas. La sintaxis with { type: 'json' } ahora es ampliamente compatible en navegadores modernos y versiones actuales de Node.js. Solo asegúrate de que tus archivos se sirvan por HTTP con el tipo MIME correcto, y estarás listo.

Preguntas frecuentes

Sí. La propuesta de atributos de importación está diseñada para ser extensible. Los scripts de módulos CSS, por ejemplo, usan with type css en navegadores compatibles. Sin embargo, JSON es el tipo más ampliamente compatible hoy en día. Otros tipos dependen del runtime y pueden no estar disponibles en todas partes todavía.

La importación fallará completamente y lanzará un SyntaxError. A diferencia de fetch donde puedes capturar e inspeccionar la respuesta cruda, una importación de módulo JSON no ofrece recuperación parcial. Valida tus archivos JSON con un linter o una verificación de CI antes de implementar para evitar fallos silenciosos en tiempo de carga.

No para la importación JSON en sí. Los navegadores modernos y Node.js lo manejan de forma nativa. Sin embargo, aún puedes querer un bundler por otras razones como división de código, tree shaking, o transpilación de sintaxis para objetivos más antiguos. El punto es que la carga de JSON por sí sola ya no requiere uno.

Los navegadores aplican reglas de seguridad estrictas en la carga de módulos. El protocolo file no admite los mecanismos requeridos para solicitudes de módulos, por lo que el navegador bloquea la importación. Necesitas servir tus archivos a través de un servidor HTTP, incluso localmente. Herramientas como Vite o el paquete npm serve manejan esto con una configuración mínima.

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