jashkenas / jashkenas/coffeescript

ES modules in Node, and .mjs files

Open
#5,018 15 comments 1 reaction 0 assignees View on GitHub
enhancement help wanted
Dominant language
CoffeeScript
Stars
16.6k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

Node 8.5 added support for [ES modules](https://nodejs.org/api/esm.html) behind the `--experimental-modules` flag. Node 10, expected to be released in [April 2018](https://github.com/nodejs/Release), will supposedly drop the flag. Here’s [a great overview](http://2ality.com/2017/09/native-esm-node.html).

Adding ES modules was mostly Node finally supporting the `import` and `export` syntax from ES2015, that CoffeeScript already supports. There is at least one caveat, though: [Node only supports importing files with an `.mjs` extension](http://2ality.com/2017/09/native-esm-node.html#why-is-the-file-extension-mjs-required-on-nodejs), [_from_ files with an `.mjs` extension](https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c).

This raises the issue of how to use the CoffeeScript compiler to generate output JavaScript files with `.mjs` extensions. If you’re using the `coffee` command to compile a single file, you can specify the output filename, including extension, explicitly:

```bash
coffee --compile --output module.mjs module.coffee
```

But for folders, the compiler automatically outputs all `.coffee` files as `.js` files. It doesn’t take much effort to add a post-compilation step that renames these extensions, but should this perhaps be something the compiler handles?

One way to do it would be to introduce a new `.mcoffee` file extension, that the compiler would output as `.mjs`. Straightforward, though the greater ecosystem around CoffeeScript would need to be updated. (Syntax highlighters, etc.)

Another way to do it would be with a new CLI flag, e.g. `--output-extension mjs`. This might be useful in its own right, to allow outputting JSX files with a `.jsx` extension (if for some reason you wanted to simply save them, rather than immediately transpiling them into JavaScript). But @jashkenas and others (including me) feel strongly against adding yet more flags to the CLI, except as a last resort.

Are there any other ways to handle this situation? Unfortunately we can’t simply output all files with `import` or `export` statements as `.mjs`, because a lot of people will want the current behavior for quite a while, as [Babel’s treatment of those statements is different than Node’s](https://medium.com/@giltayar/native-es-modules-in-nodejs-status-and-future-directions-part-i-ee5ea3001f71) and many people won’t want to refactor their code anytime soon. (A great lesson in why not to start using features before they’re both standardized and implemented!)

The other thing on my mind regarding this is that I want to rewrite the [modules tests](https://github.com/jashkenas/coffeescript/blob/master/test/modules.coffee) to use actual `import` and `export` statements that Node evaluates, rather than comparing strings; but I think the only way to do this would be to spawn a new Node process with an `.mjs` file as its entrypoint. (This is regardless of whether the `--experimental-modules` flag is still around.) This would add considerable complexity to the test runner, but I think would be worth it.

Contributor guide

Open the contributing guide

Research direction

Start with the folder-compilation behavior described in the issue and the existing test/modules.coffee tests, which currently compare module output as strings. Review the alternatives for producing .mjs files and for running Node-based module tests, then confirm which design is selected before defining completion.

Written by the indexing model from the issue text.

Assessment

Tech stack
coffeescript, javascript, node.js
Domain
build-system, cli, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.