ECMAScript proposal: JSON modules
source link: https://2ality.com/2021/06/json-modules.html?utm_campaign=Feed%3A+2ality+%282ality+%E2%80%93+JavaScript+and+more%29
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
In this blog post, we examine the ECMAScript proposal “JSON modules” (by Sven Sauleau, Daniel Ehrenberg, Myles Borins, and Dan Clark). It lets us import JSON data as if it were an ECMAScript module.
Table of contents:
Why would we want to import JSON like a module? #
Various bundlers (such as webpack) have allowed us to import JSON data as if it were an ECMAScript module for a long time. JSON modules turn this into a standard feature.
Why is that interesting? It provides a convenient way of using, e.g., configuration data in our apps. Take, for example, the following file structure:
my-app/
src/
config-data.json
main.mjs
my-app/src/config-data.json
looks as follows:
{
"appName": "My App"
}
This is my-app/src/main.mjs
:
import configData from './config-data.json' assert {type: 'json'};
console.log(`I am ${configData.appName}!`);
The syntax from assert
until the end is called an import assertion. JSON modules were one of the use cases for which import assertions were created.
The default export of a JSON module contains the JSON data. There are no named exports.
Getting JSON data via fetch()
#
Without JSON modules, we would have to use fetch()
:
async function fetchConfigData(relativePath) {
const urlOfConfigData = new URL(
relativePath, import.meta.url); // (A)
const response = await fetch(urlOfConfigData.toString()); // (B)
const json = await response.json(); // (C)
return json;
}
const configData = await fetchConfigData('config-data.json');
console.log(`I am ${configData.appName}!`);
We are using two relatively new features:
- The Fetch API, an API based on Promises for downloading files in JavaScript code (line B and line C).
- The module metadata property
import.meta.url
(line A).
fetch()
has two downsides compared to JSON modules:
- The code is slightly more complicated.
- Node.js currently has no built-in support for
fetch()
. (And I suspect JSON modules will be supported sooner thanfetch()
.)
Dynamically importing JSON modules via import()
#
The previous import
statement was static (fixed at runtime). We can also import JSON modules dynamically (changeably at runtime):
async function importConfigData(moduleSpec) {
const namespaceObj = await import( // (A)
moduleSpec, {assert: {type: 'json'}});
return namespaceObj.default; // (B)
}
const configData = await importConfigData('./config-data.json');
console.log(`I am ${configData.appName}!`);
Note that the import()
operator (line A) returns a module namespace object. That is why we return the value of property .default
(which contains the default export) in line B.
Why the extra syntax? #
You may wonder why we have to use extra syntax at the end of the important statement:
import configData from './config-data.json' assert {type: 'json'};
Why can’t JavaScript detect that this is JSON by looking at the filename extension?
import configData from './config-data.json';
This is not possible because it can cause security issues: Browsers never look at filename extensions, they look at content types. And servers are responsible for providing content types for files. Therefore, two things can happen when importing a .json
file:
- Our own server might send a content type other than
application/json
and the importing would go wrong in some manner. - 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.
Therefore, JavaScript won’t rely on content types when importing JSON.
Availability #
- Chrome 91 supports JSON modules (source: Chrome Platform Status).
More information on modules in JavaScript #
- Chapter “Modules” in “JavaScript for impatient programmers”
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK