Import Attributes and Type JSON in Modern JavaScript

This article explains the purpose and functionality of import attributes in modern JavaScript, focusing on type: "json". Import attributes allow developers to attach explicit metadata to module import declarations, enabling JavaScript runtimes to safely and natively import non-JavaScript resources—such as JSON documents—without relying on bundler-specific transforms or asynchronous fetch workarounds.

Preventing Security Vulnerabilities

The primary reason for introducing the type: "json" attribute is security, specifically mitigating MIME-type confusion and code execution attacks.

In standard JavaScript module loading, the runtime executes imported resources as executable JavaScript code. If a web application attempts to import a JSON file from a remote server without explicit type verification, a malicious or compromised server could return a file containing executable JavaScript with a text/javascript MIME type instead of JSON data.

By adding with { type: "json" }, the developer explicitly declares the expected format. If the imported resource cannot be parsed as valid JSON or if the server delivers it with an incompatible MIME type, the module graph instantiation fails immediately, preventing arbitrary script execution.

Native and Ergonomic Resource Loading

Historically, importing JSON required developers to use fetch() at runtime or depend on build tools like Webpack or Rollup to transform JSON files into JavaScript objects. Import attributes standardize this behavior across all environments.

Static import syntax:

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

Dynamic import syntax:

const data = await import("./data.json", {
  with: { type: "json" }
});

Using these native constructs, JSON files become full participants in the ECMAScript Module (ESM) graph, allowing synchronous-like access at module initialization without manual parsing steps like JSON.parse().

Static Analysis and Dependency Graphs

Import attributes integrate directly into the static structure of ECMAScript modules. Because with { type: "json" } is statically analyzable, JavaScript runtimes and build tools can build accurate dependency trees before executing any code. This determinism allows engines to optimize resource preloading, tree-shaking, and bundling pipelines consistently across both browsers and server-side runtimes like Node.js and Deno.

Extensibility for Future Formats

While type: "json" is the most common use case, import attributes provide an extensible framework for other non-JavaScript resources. The same architecture supports additional module types, such as CSS style sheets (type: "css") and WebAssembly modules, creating a unified standard for all web resource imports.