ESNext: Import Assertions (JSON Modules, CSS Modules, …)

Did you know you can import JSON and CSS files just like you import JavaScript Modules? Thanks to Import Assertions, it’s as easy as this:

It’s a regular import statement with an extra assert { "type": … } part added to it. That way you can tell the browser to treat and parse the referenced file to be of a certain type. Once imported you can use the contents further down in your JavaScript code, just like you do with regular ES Module imports.

  "appName": "My App"
import configData from './config-data.json' assert { type: 'json' };

console.log(configData.appName); // "MyApp"


Import Assertions is currently at Stage-3, and is expected to become part of the upcoming ES2022.

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (i.e. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

Import Assertions are supported in Chromium 91+. For browsers that don’t support it, you can use the es-module-shims polyfill which provides this functionality (and more nice tings)


In the most recent episode of CodePen Radio, just a little after the 10-minute mark, you can see host Chris Coyier demonstrate this (along with importing packages directly from Skypack):

The CSS example Chris shows there uses Lit. In a non-framework environment, add the imported styles using Constructed Stylesheets:

import styles from "./styles.css" assert { type: "css" };
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];

💡 Do note that adoptedStyleSheets is only supported in Chromium browsers at the time of writing (CanIUse).


If you’re wondering why we can’t simply import those files directly, without the assertions, Axel Rauschmayer has the answer:

Browsers never look at filename extensions, they look at content types. And servers are responsible for providing content types for files.


With an external server, things are even more risky: If it sends the file with the content type text/javascript, it could execute code inside our app.


And oh, Import Assertions can be used with dynamic import(). Pass in the assertion as the second parameter:

const configData = await import('./config-data.json', {
  assert: { type: 'json' },
console.log(configData.appName); // "MyApp"


A future without a Build System is lurking around the corner, especially when you combine these Import Assertions with a follow-up Evaluator Attributes proposal and Import Maps 🤩



🔥 Like what you see? Want to stay in the loop? Here's how:

Published by Bramus!

Bramus is a frontend web developer from Belgium. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.