WICG/webcomponents

JSON "modules"

annevk opened this issue ยท 15 comments

At TPAC someone (sorry, forgot) brought up that import json from "./data.json"; would be neat. Should be pretty easy to branch on https://mimesniff.spec.whatwg.org/#json-mime-type and UTF-8 decode and JSON parse something...

It's nice to have but we can already handle it today. See my post

The same thing can be done with scss, typescript, images (maybe convert them to base64 or data-uri), and whatever.

The idea comes from webpack (what webpack does is converting everything into a js script). All you need to do is to find a loader.

It's much more reliable to handle it at server side, you know, for browser compatibility, unless browser send a special Accept header to indicate its support.

The same problem applies to <script type=module>. Browser still sends Accept: */* for <script type=module> so <script nomodule> exists

Perhaps you missed that this effort is about defining the (default) loader for the browser. So yes, some things can be done through a more complicated setup, but it'd be nice if in the future that could be avoided altogether.

Perhaps you missed that this effort is about defining the (default) loader for the browser. So yes, some things can be done through a more complicated setup, but it'd be nice if in the future that could be avoided altogether.

See my edited post

It's much more reliable to handle it at server side, you know, for browser compatibility, unless browser send a special Accept header to indicate its support.

The same problem applies to <script type=module>. Browser still sends Accept: */* for <script type=module> so <script nomodule> exists

But you can't assume ./data.json is a json file. Browsers never guess file type based on its extension. That's how browsers work

Different syntax like import_json data from './data.json' may work IDK. It's a syntax error without browser support, which may end up with webpack.

In addition, It's not polyfill, compile friendly. All you can choose is to compile it into a synced xhr, which is a big NONO

@annevk knows how browsers work, he's worked on them for a long time. The idea here isn't to parse specifiers ending in .json, it's to do so based on the Content-Type.

I mean that server dare not return a json document without an browser support indicator. @matthewp

Browser wont guess what .json is so they wont send a special header

@CarterLi Is this about the time period where some browsers support JSON-modules whereas others do not? And so might want to send the .json file to browsers that support it.

In the long term this won't matter as all browsers would eventually support the feature if it was added, but I definitely see that having browsers use an Accept header would make it simpler as new formats are added as you could just give a webpack-ed module to a browser with the header Accept: text/javascript but provide JSON directly to a browser with Accept: text/javascript, application/json.

While it only really benefits the transitional periods, it may still be worthwhile as more module formats (e.g. Wasm, HTML modules, etc) are in development so there's likely to be a long set of transitional periods for various module formats.

@Jamesernator I've opened the issue above to add a default Accept header of JavaScript MIME types to JS module requests, which would encourage being overridden with values that make sense once the browser supports other MIME types.

Pardon my ignorance, but I'm curious why this is needed?

file-a.js

export = {
  a: 'a'
}

file-b.js

export = {
  "b": "b"
}

Importing both of those result in the same thing...doesn't it? Why would json need any special treatment? Eliminates the need for export = ? or supports the .json file extension?? Interested in learning more if someone can explain...

@jfbrennan Did you mean export default { "b": "b" }? In which case the advantage of true JSON modules would be that people can use existing tools for generating and processing the files without worrying about adding or stripping a magical prefix.

Yeah, both examples - export = {} and export default {} - are valid js, but not valid JSON because of the export statement.

From my limited knowledge on this topic you can already successfully import JSON. I import package.json with no problems. Although I guess I'm require()ing it and that's servers-side only...anyway, just trying learn and was curious why @annevk and others apparently see this as a need.

rniwa commented

Independent of whether this particular proposal is good or not, JSON files are better than JS files in terms of security because its content can't be loaded cross origin without CORS, and it's a CORB protected MIME type.

If, for example, the JSON contains information that should be only visible to a logged in user, for example, then it's not sound to turn it into a JS file without a Cross-Origin-Resource-Policy header because such a file could be loaded cross origin without CORS.

My primary motivation for this is convenience. If you want to use a JSON resource as some kind of input you should not have to turn it into JavaScript in order to be able to make use of it. And requiring fetch() for JSON resources instead would require significant concessions when setting up a module graph (basically cannot use the declarative form as I understand it).

So import json from "./data.json" doesn't work the way you'd expect it to? With just that one line json is still a string that needs JSON.parse(json) or something? Haven't tried that before...

Ah! Never mind. It fails completely: "Failed to load module script: The server responded with a non-JavaScript MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec."

Now I see. Thanks for helping explain

We are exploring an implementation in Node.js in nodejs/ecmascript-modules#43

FYI: this has also been discussed in the HTML Standard's repository at whatwg/html#4315 and there's now a PR at whatwg/html#4407. There's a couple minor issues still to be sorted, but thus far it seems highly likely this feature will make it.