MikeMcl / bignumber.js

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic
http://mikemcl.github.io/bignumber.js
MIT License
6.64k stars 741 forks source link

import { BigNumber } gave an Error #300

Closed emmtte closed 2 years ago

emmtte commented 3 years ago

Hi,

With NodeJS 14 or 16

import BigNumber from "bignumber.js"; this work fine but

import { BigNumber } from "bignumber.js"; have this error

import { BigNumber } from "bignumber.js";
         ^^^^^^^^^
SyntaxError: Named export 'BigNumber' not found. The requested module 'bignumber.js' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'bignumber.js';
const { BigNumber } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:121:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:171:5)
    at async Loader.import (node:internal/modules/esm/loader:178:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5)
    at async handleMainPromise (node:internal/modules/run_main:63:12)
MikeMcl commented 3 years ago

Yes, if you are not using a bundler such as webpack or rollup which uses the module field of the package.json, then you would need to import using the path to the module file

import { BigNumber } from "./node_modules/bignumber.js/bignumber.mjs";

Notes:

I am not absolutely sure about this, but in earlier versions of Node (<13?),

import { BigNumber } from "bignumber.js";

would work, because the "main" field in the package.json here is extensionless, and the old import path resolution algorithm looked for a file with the ".mjs" extension first. See 4.4. Shipping both ESM and CJS and Dual-Mode Packages.

That is no longer the case, so now

import BigNumber from "bignumber.js";

will actually load the bignumber.js file rather than the bignumber.mjs file, and only the default export is available when importing from CommonJs files, so named exports such as in

import { BigNumber } from "bignumber.js";

no longer work.

The new import resolver algorithm is here.

The solution is to add the "exports" field to the package.json

"exports": {
  "import": "./bignumber.mjs",
  "require": "./bignumber.js"
}

but that will prevent importing from subpaths of the package, for example

import { BigNumber } from "./node_modules/bignumber.js/bignumber.mjs";

so it likely to cause some users problems initially.

I also need to consider typescript, webpack, rollup, angular etc.

Related: Modules: Packages Hybrid npm packages (ESM and CommonJS) ES Module not used in preference to CommonJS module for big.js big.js is a CommonJS dependency

217 #278

emmtte commented 3 years ago

OK, thanks for your help