Skip to content
This repository was archived by the owner on Sep 2, 2023. It is now read-only.
This repository was archived by the owner on Sep 2, 2023. It is now read-only.

Feature: ESM in .js files #151

Closed
Closed
@GeoffreyBooth

Description

@GeoffreyBooth

There needs to be a way to tell Node to treat .js files as ESM JavaScript.

Besides the issue raised in #149, there’s the use case of legacy build tools and pipelines that expect only a single file extension for JavaScript. I can give a concrete example for the case of CoffeeScript. The problem is that essentially, the CoffeeScript compiler is a string converter. It takes a string as input, like console.log 'hello!', and returns another string as output: console.log('hello!'); People who use the CoffeeScript compiler as their entire build chain (as opposed to using it within Gulp or Webpack or the like) use it to transpile projects like this:

coffee --compile --output dist/ src/

This command recursively searches src/ for all *.coffee, *.litcoffee and *.litcoffee.md files, runs them through the CoffeeScript compiler, and saves them as *.js files in a mirrored folder tree under dist/.

CoffeeScript doesn’t know the parse goals of the files in src/. It doesn’t know which ones to save with a .js extension versus an .mjs extension. About the only way it could know is if we created new file extensions, like .mcoffee, .mlitcoffee and .mlitcoffee.md, that it knew to output as .mjs. But that’s not a practical solution, as there are thousands of CoffeeScript build plugins and syntax highlighters and so on out there that would need to be updated to support these new file extensions; and let’s be honest, most of those packages are abandoned. Adding a new option, like --output-file-extension mjs, also isn’t realistic for the same reason, because of the sheer number of build plugins that would need to be updated to support it. CoffeeScript traditionally just converts one string into another, without necessarily reading or passing along any other options or metadata, and there are lots of build pipelines that expect this behavior.

Rather than figuring out a way to add a piece of metadata (the parse goal) to CoffeeScript source files, and then updating all other parts of the build chain to preserve and pass along and understand this new metadata, it would be better if the parse goal could be specified outside of the file itself.

There’s already one implementation to achieve this: nodejs/node#18392, which suggests a mode flag for package.json files to tell Node to treat .js files as ES modules within a given package boundary. There’s also the suggestion here expand that idea to create a whole new section in package.json where users can assign MIME types for file extensions, essentially telling Node how to parse any type of file. Either of these solutions would work.

We have the same issue for input that doesn’t come from files, such as from STDIN or via --eval. There needs to be some way to tell Node to treat those inputs as ESM, such as a CLI flag:

node --module --eval 'import path from "path"; console.log(path.sep);'

These suggestions are complements for .mjs, not replacements. These proposals don’t provide easy ways to keep CommonJS and ESM files side-by-side in the same folder, for example. These are solutions for use cases that go unfulfilled by .mjs.

One final note: I don’t claim to speak for other compile-to-JavaScript languages, like TypeScript or JSX, but I wouldn’t be surprised if many of them had similar issues. There are also other categories of build tools and plugins, like linters and minifiers, that may be affected. For maximum compatibility, we should provide multiple ways to signal ESM mode to Node.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions