Description
Motivation
Deciding on the module format is one of the most important parts of getting a JavaScript library published on NPM.
A leaf project usually uses only one format, but a library does not. There are several ways:
- CommonJS-only: CJS is still the most common module format in Node.js. It is also compatible with projects using ESM. But the problem is that it is not standard and therefore breaks interoperability with other JS platforms like Deno, Bun, Browsers.
- ESM-only: ESM is standard. Adoption rates are growing, but there are still many gaps. One major problem is that it is not compatible with projects using CJS.
- Dual-package publish: To resolve the problems, Node.js has adopted a relaxed module resolution mechanism since v16+. Libraries can support both CJS/ESM projects with that in mind.
I've introduced the dual-package publish method using bundler on a forum: Bundle ReScript libraries with dual-package exports
However, the ReScript compiler today only supports one package-spec at a time and doesn't offer enough customization options, so we have to rely on external tools to do that.
Babel has env
options for transpile multiple target once, TypeScript can customize project config file, so users can do that by just run tsc
twice.
But it's still difficult, even with external tools. I've automated it to some extent, but there are tricky tasks like fixing the bs package-spec
to es6
for compatibility, adjusting the module resolution in the output, and linking the correct libraries, etc.
I want ReScript to be a good option for libraries as well. It will eventually lead to ReScript-first projects and increased adoption.
Design
Introduce a new package-spec
mode dual
to support dual-package libraries.
{
"package-specs": {
"module": "dual",
"in-source": true
}
}
Which means ReScript should emit both CommonJS and ESM. To adjust the extension of the outputs, the suffix
option must also be expanded.
{
"suffix": {
"commonjs": ".cjs",
"esmodule": ".mjs"
}
}
To use dual
, suffix
must be specified as an object, a unique and valid extension for each format must be specified.
As a result, the A.res
module has A.cjs
and A.mjs
outputs at the same time. This is the minimum requirement for publishing a dual package and should be sufficient to use ReScript as the only toolchain for a library.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Status