Enable better ESM compatibility #45
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR makes the package properly compatible with ES modules and allows NodeJS to load the library as an ESM, rather than CommonJS.
Currently, if you try to
import(ESM style) random-js into a library, rather thanrequire(CommonJS style) and are not using a bundler (e.g. RollUp, Webpack), then it throws an error:Changing it to use:
Does work, in some situations, but not all; a key one that fails is Jest, as it doesn't seem to like loading a CommonJS file with
import.So, currently, you can only use random-js in an ESM package if you're using a bundler. This wasn't really an issue before, when all ESM stuff would need to be parsed and bundled to work (As ESM wasn't compatible everywhere). However, this is no longer necessary, and Node supports native ESM. NodeJS enviroments are rarely bundled, because you don't need to compress the files server side.
By adding an
exportsproperty to the package.json, it tells node which files to use forrequire(CommonJS), and which files to use forimport(ESM).This works when running a file natively in node (
node foo.js), when running with Jest, and also with package bundlers.A side effect of this, is that the library has also been specified as
"type": "module"which means that node expects all*.jsfiles to be ES modules, and*.cjsfiles to be CommonJS.So I've renamed the
benchmark/*.jsfiles tobenchmark/*.cjsso they still work.And I've had to change the build script to place the ESM and UMD build in their own directory. This is because I didn't want to change the UMD file extension to
.cjsas it wouldn't then work in a browser (Browsers don't understand the.cjsextension). However, you can place a package.json file in a directory to specify the type for files in the directory. So I've added one to the UMD directory.So they're now built to:
dist/random-js.esm.js(old) ->dist/esm/random-js.js(new)dist/random-js.umd.js(old) ->dist/umd/random-js.js(new)I also updated some dependencies, otherwise RollUp and Jest couldn't parse the TypeScript files (I'm guessing the older versions didn't understand ESM packages).