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

Written by / Original link on Oct. 14, 2021


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:

Building upon "Import Assertions" we recently saw JSON Modules land in V8/Chromium 91:

import json from './foo.json' assert { type: 'json' };

In Chromium 93 the same thing for CSS lands (“CSS Modules”):

import styles from "./styles.css" assert { type: "css" };

— Bramus (@bramus) July 30, 2021

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.

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 (e.g. 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.


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:

  "appName": "My App"
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:

bram tutorialzine tutorialzine esnext bram calevans modules bram

« Tachometer – Statistically rigorous benchmark runner for the web - How I built a modern website in 2021 »