Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ".mjs" input files #27957

Closed
mjbvz opened this issue Oct 18, 2018 · 106 comments
Closed

Support ".mjs" input files #27957

mjbvz opened this issue Oct 18, 2018 · 106 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@mjbvz
Copy link
Contributor

mjbvz commented Oct 18, 2018

From @Sti2nd on October 7, 2018 16:17

import { timpaniSounds } from "./soundImport.mjs";

In the above example VS code will show all javascript files when writing "./", but not javascript module files. So I didn't see the above file in the list when trying to import it.
Not sure if this is a bug or a feature request.

Copied from original issue: microsoft/vscode#60103

@mjbvz mjbvz self-assigned this Oct 18, 2018
@mjbvz mjbvz added the Domain: JavaScript The issue relates to JavaScript specifically label Oct 18, 2018
@mjbvz mjbvz removed the Domain: JavaScript The issue relates to JavaScript specifically label Oct 18, 2018
@mjbvz mjbvz removed their assignment Oct 18, 2018
@mjbvz mjbvz added the VS Code Tracked There is a VS Code equivalent to this issue label Oct 18, 2018
@mjbvz
Copy link
Contributor Author

mjbvz commented Oct 18, 2018

I believe that #18442 tracks compiling typescript to mjs. Do we fully support working with mjs files in the editor?

@mjbvz mjbvz removed VS Code Tracked There is a VS Code equivalent to this issue labels Nov 1, 2018
@weswigham
Copy link
Member

We don't lookup or include .mjs files in any way at present, since it's going to be used as a flag in node that changes module resolution and the exact behavior it switches on (W.R.T. cjs interop) is still TBD, interpreting it would be putting the cart before the horse.

@weswigham weswigham added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Nov 1, 2018
@weswigham weswigham changed the title No autocomplete for ".mjs" files Support ".mjs" input files Nov 1, 2018
@weswigham
Copy link
Member

Since the other thread tracks .mjs output, I'll repurpose this one for tracking .mjs input.

@vincentvictoria
Copy link

vincentvictoria commented Dec 12, 2018

I think it comes down to a standardization issue: javascript modules must have a standardized file extension.

It's causing troubles to us, and I believe everyone who are making modules targeting for both browser & node are affected.

In browser, we have to specify file name with extension:
import { SuperModule } from './SuperModule.mjs';

But vscode doesn't recognize .mjs, so we resort to changing extension to .esm.js
import { SuperModule } from './SuperModule.esm.js';

Then node doesn't recognize .esm.js as a module unless we specify a different loader which recognizes the extension:
'node --loader esmloader.js index.js'

This is surely uncomfortable since you have to specify a non-default loader.

Either node has to support .esm.js or vscode has to support .mjs. for short-term solution.

I personally think module javascript files gotta have a different extension since it's treated differently in both browser & node. Browsers require:
<script type='module' src='script.js' />
See, browsers also need to know it's a different type of javascript before loading. I think a different extension is rightful for the purpose.

I prefer .mjs since it's funny (Hello, Michael Jackson), short and right for the purpose.
I'm using .esm.js right now, but it's very cumbersome to write. And i have to specify type='module' in the browser anyway even if i already typed '.eeeessssmmmm.js'

I just hope es7/8 standard specify that javascript modules must have .mjs extension.

@robertrossmann
Copy link

I crafted a patch which enables tsserver to recognise, parse and provide type hints for .mjs files.

This might be useful for people who use the .mjs file extensions for JavaScript files with identical module resolution semantics as CommonJS. Note that this patch does not implement any special behaviour with regard to ES modules and might not be spec-compliant. However, editor integrations which allow using custom-built tsserver implementations will greatly increase developer productivity because suddenly everything seems to work.

@vincentvictoria
Copy link

Thanks for the patch, @robertrossmann!

Btw, I just realized that tsserver recognizes jsx. Then, why not mjs? Both are not ES spec, but at least industry standards.

@mathiasbynens
Copy link

We don't lookup or include .mjs files in any way at present, since it's going to be used as a flag in node that changes module resolution and the exact behavior it switches on (W.R.T. cjs interop) is still TBD, interpreting it would be putting the cart before the horse.

As of last October, there’s agreement on the “minimal kernel”, which states that:

  • import statements will only support files with an .mjs extension, and will import only ES modules, for now.
  • In a later phase, the intention is to move forward with format databases to map extensions and support multiple use cases.

@mathiasbynens
Copy link

In other words, there’s no point in waiting. .mjs signals that the file is a JavaScript module, now (in the experimental implementation) and in the future (per the acceptance of the minimal kernel).

@puneetpr
Copy link

puneetpr commented Apr 9, 2019

is there any stop-gap workaround that we are aware of?

@philipwalton
Copy link

Hey @weswigham, can you please bump the priority on this issue?

This is currently preventing anyone who uses TypeScript from building a custom service worker bundle with Workbox, since Workbox's source code is published as .mjs (to disambiguate the source modules from it's built, classic scripts, which have to be .js since browsers don't currently support loading modules in workers).

Workbox users can do this with Webpack, they can do it with Rollup, and they can do it with Parcel, but they can't do it with TypeScript, and many of our users are TypeScript users.

From the above discussion it sounds like you wanted to wait to see where node landed on .mjs, but regardless of what node does, the fact is this affecting real users today. Many Workbox users are filing issues for this or complaining about it on our Slack channel or on Twitter.

It's a real blocker for a lot of people, and it's not something we can change on our end since that would break people's existing builds. There are also lots of other modules (browser modules, not just node-specific modules) that are published to npm with .mjs source files, and this is an issue for any TypeScript users wanting to consume those as well.

I don't see any downside to TypeScript recognizing .mjs as a valid JavaScript file, and I think that would be the simplest way to resolve this problem real users are having today.

@TimvdLippe
Copy link
Contributor

Aside from the actual TS inputs, click-through in VS Code (e.g. ctrl-click on import 'foo.mjs') does not work. If I change it to import 'foo.js', VS Code correctly understands the file and correctly jumps to definition. Since the browser ignores the file extension and only requires the correct MIME-type, I am unable to author my code in .mjs (or whatever extension I would prefer) with VS Code, while it runs just fine in the browser.

frank-dspeed added a commit to frank-dspeed/content that referenced this issue Aug 5, 2021
The Article got Partial pasted into a discussion in microsoft/TypeScript#27957 (comment) and i found out that it makes false claims that confuses new users. So i corrected the relevant parts as the Users do not understand that we migrate forward to ESM and not ship old none needed CJS if it is not needed.
@frank-dspeed
Copy link

@igorskyflyer mdn/content@main...frank-dspeed:patch-1 i will patch the MDN Article thanks for your input. it Helps us to identify Areas where the information is not as clear as it should be

@igorskyflyer
Copy link

@frank-dspeed, I agree, I am for that too but we are not there, yet. This is my opinion during this transition period until there is one standard in both Node and browsers. Also, the opinions I stated above are based purely on (available) facts and personal experience, I never said it makes the code better in any way, more compatible - yes.

Sidenote, this issue is about .mjs importing issue during development in Visual Studio Code but .cjs doesn't work as well.

@frank-dspeed
Copy link

@igorskyflyer thats true without patching typescript there is no chance and the typescript philosophie is against that you need to wait for alternativ resolve algo support. maybe it already even works i am not so deep into that.

but there are internals to allow diffrent resolve strategies.

for example import maps maybe already work and package,json works already

or adding // @ts-check on top of the file also works

@petamoriken
Copy link
Contributor

FYI: https://datatracker.ietf.org/doc/html/draft-ietf-dispatch-javascript-mjs-09

@frank-dspeed
Copy link

@petamoriken can you please explain more deep why this is related to the deprecation of existing mime types ?

@petamoriken
Copy link
Contributor

@frank-dspeed This draft also includes the adoption of .mjs as the new file extension for JavaScript 🙂

It is not possible to fully determine if a Source Text of ECMAScript is meant to be parsed in the Module or Script grammar goals based upon content alone. Therefore, scripting environments MUST use out of band information in order to determine what goal a Source Text should be treated as. To this end some scripting environments have chosen to adopt the new file extension of .mjs for this purpose.

https://datatracker.ietf.org/doc/html/draft-ietf-dispatch-javascript-mjs-09#section-3

@frank-dspeed
Copy link

frank-dspeed commented Sep 21, 2021

@petamoriken i only read SOME (NodeJS) scripting environments have chosen ......

The Browser will stay with mime headers There is 100% sure zero effort in changing that. The Script Parsing type inside the browser gets declared via the script type the headers will stay the same.

NodeJS is the only driver for .mjs

Out of Browser view

  • mime header
  • type property of the script tag

Example

to be more clear this will never work with esm modules!

<script src="/my.mjs"></script>

and this will always work

<script src="/my.mjsOrNoMatterwhat" type="module"></script>

Out of Typescript view

  • JS or TS extension to init JS Parsing || Putting //@ts-check on top of a file with .AnyExtension
  • Typescript determins the JS Type when it parses export/import statements + tsconfig.json

Out of NodeJS view

by the way the only none well speced implementation that supports a lot of mixUps

  • package.json + || .ext || loaders || flags

Out of Embeddeder view

Embedders are projects that are using v8 or other popular engines directly

  • the embedder calls the engine init with the parsing type

@igorskyflyer
Copy link

igorskyflyer commented Sep 21, 2021

@frank-dspeed, just to be clear, this:

<script src="/myModule.mjs"></script>

was never proposed nor supposed to work - as far as I am aware of. The attribute type with a value of module is mandatory for a given JavaScript file to be parsed as a module. Thus, the final code should look like:

<script src="/myModule.mjs" type="module"></script>

Also, .mjs files/scripts work perfectly fine after defining their MIME type on the server, tested on XAMPP.

@frank-dspeed
Copy link

@igorskyflyer i did list all requirements including the mime header and in my example i did .mjsOrAny to demonstrate that it has nothing to do with the extension. and your correct without type it is not suposed to work you maybe did not read the whole story.

@igorskyflyer
Copy link

@frank-dspeed, my apologies then, I skim-read the comment. Either way, it is evident that we are still waiting for a unique solution for this mjs/modules hell. 😭😅

@frank-dspeed
Copy link

frank-dspeed commented Sep 22, 2021

@IgorNovozhilov There is no real module hell anymore the way forward is clear simply drop cjs usage call the files .js and configure typescript correct per folder.

Sure i agree it is a lot to know and do but it is not unsolved at all and .mjs remains a nodejs only topic.

Update for thumbs down

I want to offer some more detailed Information as there are still people who did not get it.
You should create dev-bundels of your dependencies. isolate the packaging of your vendored dependencies from the Main Application that your creating. This will lead to consistent dependencies.

also this got now fixed via a new moduleResolution algo called "node12" as this is a node only thing

@weswigham
Copy link
Member

Fixed by the addition of module: node12 with #45884 (which includes support for .mjs and .mts files).

@frank-dspeed
Copy link

this future will only be in typescript 4.6 it got droped from the 4.5 time schedule #46452 (comment)

as Daniel (TypeScript Team Lead) pointed out

@weswigham
Copy link
Member

(Technically support did ship in 4.5, it relies on the module: nodenext setting, it just issues an error saying it's experimental)

@frank-dspeed
Copy link

@weswigham does nodenext include everything that was included in node12 (package.json exports fild)?

@weswigham
Copy link
Member

They're mostly the same (except for some export map edge cases and the implied target), and both modes are included.

@knightedcodemonkey
Copy link

Is this really fixed? It doesn't seem so, at least not in all use cases. Particularly, there is no way to support a mixture of .mts and .ts when using --module commonjs, all the emitted .mjs files will be broken and not consumable by either module system. It is impossible with tsc as far as I can tell, so I would not consider this fixed.

For the reason why, see my comment on #50985. This should be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet