random-js
random-js copied to clipboard
Enable better ESM compatibility
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 than require
(CommonJS style) and are not using a bundler (e.g. RollUp, Webpack), then it throws an error:
import { browserCrypto, nodeCrypto, MersenneTwister19937, nativeMath, Random } from 'random-js';
^^^^^^
SyntaxError: The requested module 'random-js' is expected to be of type CommonJS, which does not support named exports. CommonJS modules can be imported by importing the default export.
For example:
import pkg from 'random-js';
const { browserCrypto, nodeCrypto, MersenneTwister19937, nativeMath, Random } = pkg;
Changing it to use:
import pkg from 'random-js';
const { browserCrypto, nodeCrypto, MersenneTwister19937, nativeMath, Random } = pkg;
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 exports
property to the package.json, it tells node which files to use for require
(CommonJS), and which files to use for import
(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 *.js
files to be ES modules, and *.cjs
files to be CommonJS.
So I've renamed the benchmark/*.js
files to benchmark/*.cjs
so 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 .cjs
as it wouldn't then work in a browser (Browsers don't understand the .cjs
extension). 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:
-
ESM:
dist/random-js.esm.js
(old) ->dist/esm/random-js.js
(new) -
UMD:
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).
#65 already has it's own fix for this, by simply using a command line switch during the build