Can't use mathjs without package bundler
See original GitHub issueThe problem
I’m trying to use mathjs inside node, using ES modules, but without a package bundler (e.g. Webpack, Rollup).
When I do:
import { evaluate } from 'mathjs';
console.log(evaluate('1+2'));
It throws:
import { evaluate } from 'mathjs';
^^^^^^^^
SyntaxError: The requested module 'mathjs' 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 'mathjs';
const { evaluate } = pkg;
From what I can see, the module
entry in package.json
is only used for package bundlers. Without bundlers, node will look at the main
entry, so it tries to load the CommonJS / UMD script.
Node does support mixing ES and CommonJS modules, but expects a single, default export. Changing the import to this works, because it correctly loads the CommonJS module:
import mathjs from 'mathjs';
console.log(mathjs.evaluate('1+2'));
So that’s a kind of workaround, but it does mean that it’s not using ES modules in an ES module project.
But the bigger issue is that it’s now incompatible if I choose to use to use a bundler because the bundler will use the ES module version, which has no default import. In particular, this causes my Jest tests to fail. In my test I have something like:
TypeError: Cannot read property ‘evaluate’ of undefined
I think that conditional exports may be a solution. It seems to allow you to tell node which files to use for CommonJS require
and which to use for ES import
.
Potential solution
I’ve not had a proper play with it, this seemed to work for me:
Change the package.json
to this, to tell node to use the esm
files for import
statements, and es5
files for require
:
{
"main": "./main/es5",
"module": "./main/esm",
"exports": {
"import": "./main/esm/index.js",
"require": "./main/es5/index.js"
},
// this is required, otherwise the `exports` doesn't work
"type": "module"
}
But because the type
is now module
, node will now complain when trying to use CommonJS.
To sort that, you can either rename all of the CommonJS files to have the .cjs
extension, or to add a package.json
in the root directories containing the CommonJS files (e.g. main/es5/
, lib/
), with just the following:
{
"type": "commonjs"
}
I’m not sure if doing this has any adverse affects on other parts of the library though, but I’m happy to get a PR in for those changes.
I thought it seemed similar to #1766. Not quite the same issue, but possibly the same resolution, perhaps used with Subpath Exports.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:13 (12 by maintainers)
Was this fixed by #1941, or is it still an issue?
Also, feel free to be ruthless with your review. I’m happy to change things, or scrap it, if it’s not what you’re after.