Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable better ESM compatibility #45

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

GreenImp
Copy link

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).

@GreenImp GreenImp force-pushed the feature/esm-compatible branch 4 times, most recently from d71176c to 0793797 Compare June 24, 2023 12:51
@rawr51919
Copy link

#65 already has it's own fix for this, by simply using a command line switch during the build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants