Modules: MIME types

Created on 9 Jul 2018  Â·  13Comments  Â·  Source: nodejs/modules

Hi,
I want to open an issue dedicated to MIME types. MIME types are mentioned fairly often in the issue https://github.com/nodejs/modules/issues/142 but their relevance is not entirely clear for me. Since the other issue is already extremely long, I prefer to open a separate issue.

I would like a clarification about the relation between MIME types, ESM and Node.

Here is what I currently understand, please correct anything wrong and provide more details to clarify the role of MIME types.

  • The authoritative source for MIME types for scripting files is RFC4329
  • There is a pending update for this RFC: ECMAScript Media Types Updates
  • The default MIME type for .js is text/javascript
  • A file loaded by <script src=...> or <script type="module" src=...> can be served with any MIME type, browsers don't care: <script src=...> will use the _Script_ goal, <script type="module" src=...> will use the _Module_ goal.
  • Browser will also ignore the MIME type of transitive dependencies of ESM (static or dynamic import) and treat these dependencies as ESM (even if they are obviously not: example application/wasm)
  • Node uses internally the MIME type application/node for the script file (for which extensions: .js, .mjs, .node?!). Where is it used? Why? Are servers supposed to serve files with this MIME type?
  • The IETF proposal recommends the same MIME type (text/javascript) for both .js and .mjs.
  • The IETF proposal recommends the use of the optional goal parameter for the parse goal. So files with the _Module_ goal can be served using text/javascript;goal=Module, files with the script goal can be served with the text/javascript;goal=Script MIME type.
  • The IETF proposal recommends .mjs to mean text/javascript;goal=Module
  • The browsers don't care about the goal MIME parameter currently.
  • There is a PR so if the goal parameter is present, the browsers must error if the goal used by the browser does not match the goal served by the server.

Most helpful comment

Just to be clear, I think the only update that would potentially need to be done is to update application/node so that under “File extension(s): .js” we add .cjs. I think I asked about this back when .cjs was first proposed and the response was that we wanted to wait until unflagging, if I remember correctly. So maybe in a week or so we can submit the revision to make that happen.

As far as I'm aware there’s no official registration for file extensions: it goes MIME type ➡️ one or more extensions, but not the other way around.

All 13 comments

I generally use MIME to disambiguate the format of a given blob that is to be processed. It corresponds to some sort of grammar/evaluation structure for that format. It is generally obtained through file extension or the HTTP content-type: header.

The default MIME type for .js is text/javascript

Yes and no, it is a MIME type that is registered for .js, but there are several others including application/node (CJS).

A file loaded by

@GeoffreyBooth you can setup custom content-type headers in the various CDNs and storage services across a variety of platforms:

Most CDNs also allow uploads directly or through proxying to websites. If they proxy to websites they will use the content-type from the HTTP requests that they send out. So we would mostly be concerned with situations where they are not configurable which primarily is though uploading files through things like .zip files, FTP, etc.

I do think there is a point of pain here, but it isn't major if Node provides some way to load .js files as text/javascript and since we face similar problems if people upload application/node files as text/javascript like today. We haven't seen significant backlash from people about using .js for something that the browser is unable to load with putting application/node files out on servers with the wrong content-type so I do wonder if all of this discussion about the "default" MIME needing to be the same is already disproven.

Node choosing how to parse a file, for example deciding if a .js file should be treated as CommonJS or as ESM, is equivalent to the webserver deciding what MIME type to serve for the file: application/node (CommonJS) or text/javascript (ESM). Because no browser supports CommonJS, though, pretty much no webserver will serve .js as application/node, even if sometimes it should (because it might not be executable in a browser context). So webservers generally serve all .js files as text/javascript or application/javascript, which are interchangeable.

However, application/node and text/javascript are not interchangable. Misidentification of format is exactly what you are claiming we should avoid. Right now we have no disambiguation mechanism that works across platforms, so we should solve that problem instead of endorsing misidentification of format as a reason to throw out static knowledge of a format. I don't see this statement as a point in the argument either for or against matching the web since it seems self contradictory to me.

The complication for --experimental-modules is that webservers also serve .mjs as text/javascript. So both .js and .mjs are served with the same MIME type on the Web, and therefore webservers aren’t disambiguating between Script (traditional) JavaScript and Module (ESM) JavaScript—you can save your ESM JavaScript file with either a .js or an .mjs extension, and either will work just fine on the Web. Whereas --experimental-modules doesn’t treat these identically—it loads .js as if it were a webserver serving it as application/node, a.k.a. CommonJS, so if your .js file contains import or export statements that file will throw an error.

Yes, because we don't have another disambiguation mechanism. That is why things like https://github.com/nodejs/node/pull/18392 are attractive and should be looked into. This statement you make is not a point towards wanting ambiguity and wanting the format of a given file to be unable to be known ahead of time, it is just a statement about needing to keep improving our use case satisfaction by having disambiguation be exposed in such a way that people could use .js as text/javascript.

I am closing this issue because I feel that the MIME types were clarified. You can still comment if you want to.

I noticed that the IANA draft is still being updated (e.g. https://datatracker.ietf.org/doc/draft-ietf-dispatch-javascript-mjs/ was updated just last week), but the draft makes no mention of the .cjs extension that has been used by --experimental-modules for over a year now. 🤔

@Jessidhia .cjs is CommonJS and would be under application/node not under text/javascript so it wouldn't be in that draft. An update could be done for application/node if desired but would be separate from that draft.

I think we were not too concerned about a standards registration for .cjs since CommonJS is de-facto a node internal format and I wouldn't expect things like web servers to actually care about sending the proper mime type.

@jkrems I don't disagree in a sense of urgency, but I personally want to urge taking a less cut-and-dry view on such matters.

When in rome so to speak… JavaScript, MIME, those things come with their own concerns for our consideration, and so we are losing sight of those considerations when we resolve to making concrete what can be fairly just a preference-to-not-bother-yet?!

The thing about MIME is that it needs to be distinct today, and tomorrow… and we cannot claim we know how things will look (or how they do already) and so that would be with due respect to the rationale that it is just internal as of yet.

Fair to keep in mind that application/node is hardly uniquely specialized and/or branded enough to compared application/postscript or text/javascript and so with it being watery, we would be aversive to pitfalls from conflicts by applying.

The thing about JavaScript is that it goes places, and one of those is renderers that do consume either formats, and so far that worked without MIME, but no one used MIME back then anyways… this is no longer going to be the case, I mean, if we needed them, they probably will too.

All around, not the right time today, but not cut and dry… fair?

Just to be clear, I think the only update that would potentially need to be done is to update application/node so that under “File extension(s): .js” we add .cjs. I think I asked about this back when .cjs was first proposed and the response was that we wanted to wait until unflagging, if I remember correctly. So maybe in a week or so we can submit the revision to make that happen.

As far as I'm aware there’s no official registration for file extensions: it goes MIME type ➡️ one or more extensions, but not the other way around.

Was this page helpful?
0 / 5 - 0 ratings