Now, I want to run some modules in a NodeJS environment. node would bark on me by asking to either to use .mjs extension for modules or to add:
"type": "module"
to my package.json. OK, no problem, let’s update package.json. So far, so good, everything works now.
Then I want to add a dependency on a 3-rd party ReScript library. Say, rescript-jest, rescript-test, whatever.
Once this is done, *.res files of such a library are compiled to *.bs.js along with my sources, with the settings defined by bsconfig.json. That’s quite logical.
But, I can no longer run the project with node because it wants either .mjs extension or type: module for that library. I can’t change its package.json because I have no control over it, and that library author can’t specify the type because he does not know the context where the library is going to be used.
A viable option would be switching to *.bs.mjs suffix, but there’s no such option. I have to either:
use plain .mjs suffix with in-source build and get file tree cluttered with no ability to distinguish between hand-crafted and generated sources;
use plain .mjs suffix with out-of-source build and get much pain with long/relative/paths/to/compiled/es/modules.mjs instead of just ./modules.mjs; and loose an ability to quickly switch between res and its corresponding JS in IDE;
use kludges like babel to make node think I’m using CJS-modules
Is there a particular reason why do we have ".js", ".mjs", ".cjs" or ".bs.js" options and not ".bs.mjs"?
It’s a string enum unfortunately.
If I change it to your suggestion I get:
File "/Users/florian/Desktop/test/bsconfig.json", line 8:
Error: expect .bs.js, .js, .cjs, .mjs here
For more details, please checkout the schema https://rescript-lang.org/docs/manual/latest/build-configuration-schema
I guess if changes happen on this front, we could also switch to
I’m asking it here to know are there some corner stones preventing us from having such options. I see no obstacles, but who knows. And if there’re indeed no reasons to not introduce .bs.mjs, .bs.cjs, .res.js, .res.mjs, .res.cjs, it should be confirmed by the core team and we as the community should make the improvement.
Also struggled with ESM recently. I came to a conclusion that we should avoid usage of the "type": "module" for ReScript libraries and the only way to work with ESM is to set "type": "module" for an application and compile with *.mjs suffix. And it’s a big problem not being able to distinguish between hand-crafted and generated sources.
And there are some cases why "type": "module" won’t work for a ReScript library:
An application where the library is used has "type": "commonjs", "module": "commonjs", and "suffix": ".bs.js" - then there’s an error “require() of ES Module is not supported”.
An application where the library is used has "type": "commonjs", "module": "es6", and "suffix": ".mjs" - it might work, but I have “Cannot find package ‘foo’ imported from ./bar.mjs Did you mean to import foo/entrypoints/main.cjs” in some projects, or problems with different tools that require "type": "module" for proper ESM support.
An application where the library is used has "type": "module", "module": "es6", and "suffix": ".bs.js" - There is “Cannot use import statement outside a module” if there are other ReScript libraries without "type": "module".
An application where the library is used has "type": "module", "module": "es6", and "suffix": ".mjs" - This is the only combination that works, but doesn’t look like a good idea to limit library users. It’s better to allow them decide themselves between commonjs and module using the module setting in bsconfig.
I have a library called rescript-mngutils, it is defined with commonjs, but the compiled js of this library are end up with .mjs when i change my project to es6-global and mjs suffix.
My project’s bsconfig.json
There is no need to set type with module in packages.json, so i guess may be your node version is smaller than v13.2.0.
There are no fundamental reasons why it is not possible.
The main thing is that you can see we have too many extensions and there’s a time that people don’t like names such as bs.