v16.0.0-nightly20201030e8fe38f7cfStarting from the version v16.0.0-nightly20201030e8fe38f7cf I experience the issue with named import of Dropbox:
import {Dropbox} from "dropbox";
^^^^^^^
SyntaxError: Named export 'Dropbox' not found. The requested module 'dropbox' 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 'dropbox';
const {Dropbox} = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:98:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:143:5)
at async Loader.import (node:internal/modules/esm/loader:165:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5)
Process finished with exit code 1
If I rollback to the previous nightly build v16.0.0-nightly20201029bec918fb9b, then everything is perfectly working. Therefore, I assume that the issue can be in Node.js and not in the way I import the package or in Dropbox itself.
Can it be somehow related to the Node.js transition to ecmaVersion 2021?
As the error says, 'dropbox' is a CommonJS module. This is evident as they do not have an exports key and are using main. You're going to want to use the default export instead.
import dropbox from "dropbox";
You probably added the following line recently.
import {Dropbox} from "dropbox";
Remove it since you're already doing what's necessary to import the module and destructure the class.
import pkg from 'dropbox';
const {Dropbox} = pkg;
Check out the last sentence in import statements section.
Like in CommonJS, files within packages can be accessed by appending a path to the package name; unless the package’s package.json contains an "exports" field, in which case files within packages need to be accessed via the path defined in "exports".
— https://nodejs.org/dist/latest-v15.x/docs/api/esm.html#esm_import_statements
Hope that helps. :)
/cc @guybedford This seems related to https://github.com/guybedford/cjs-module-lexer/pull/24
Code of the dropbox package: https://unpkg.com/[email protected]/cjs/index.js
Edit: it seems like it was intentional, but isn't it going to break named imports for all modules compiled with babel?
You probably added the following line recently.
import {Dropbox} from "dropbox";
No, this line was in the codebase before I've faced the issue.
Remove it since you're already doing what's necessary to import the module and destructure the class.
import pkg from 'dropbox';
const {Dropbox} = pkg;
It is proposed by Node.js in the error message, but doesn't exist in the codebase.
The problem point is that prior v16.0.0-nightly20201030 everything used to work correctly.
Is proposed by Node.js in the error message, but doesn't exist in the codebase.
If that is the case, you probably found a bug since that doesn't seem right.
If that is the case, you probably found a bug since that doesn't seem right.
I'm trying to prepare a sample project for the case reproduction.
I've succeeded to localize the issue and arranged it as a standalone IDEA/WebStorm-project.
Repro steps:
v16.0.0-nightly20201029bec918fb9bv16.0.0-nightly20201030e8fe38f7cfI'm able to reproduce:
$ curl -L https://unpkg.com/[email protected]/cjs/index.js > dropbox.cjs
$ echo "import {Dropbox} from './dropbox.cjs';" > entry.mjs
$ mkdir src
$ echo "module.exports = { default: {} };" > src/auth.js
$ echo "module.exports = { default: {} };" > src/dropbox.js
$ node-without-b92d2e4b78 entry.mjs
$ node-with-b92d2e4b78 entry.mjs
file://…/entry.mjs:1
import {Dropbox} from './dropbox.cjs';
^^^^^^^
SyntaxError: Named export 'Dropbox' not found. The requested module './dropbox.cjs' 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 './dropbox.cjs';
const {Dropbox} = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:98:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:143:5)
at async Loader.import (node:internal/modules/esm/loader:165:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5)
Related to b92d2e4b78.
@pubmikeb, thanks for doing that. Would it be possible for you to make a public GitHub repo with that instead?
@pubmikeb, thanks for doing that. Would it be possible for you to make a public GitHub repo with that instead?
Done.
P.S. Please, let me know when this repo can be deleted.
This was exactly the breaking change described in https://github.com/nodejs/node/pull/35871.
If you look at the Dropbox index file you can see it is using getters to describe the interface:
https://unpkg.com/[email protected]/cjs/index.js
Because all getters are called at the time of import, we disabled detecting getters for better compatibility as if one of those getters caused a harmful side effect then there would be no way to import Dropbox _at all_.
So this was a decision to worsten the detection in the name of compatibility. I'm open to reconsidering the exact mechanics, and we can potentially detect non-harmful getters somehow even in future to reenable this stuff, but the stable baseline not including getters seems a sensible line to draw for now.
Il misunderstood the breaking change in that PR. I thought it would special case files with an __esModule export, not just that export.
The only special case for __esModule is that it is still detected as a named export despite being a getter (import * as dropbox from 'dropbox'; dropbox.__esModule === true), not that it enables other getter detections.
(Getters are not used in Babel or TypeScript outputs, apart from for star reexports which still work correctly)
Hmm, actually in strict Babel output getters are used I see - https://babeljs.io/repl#?browsers=&build=&builtIns=false&spec=false&loose=false&code_lz=KYDwDg9gTgLgBAbzmOBfOAzKEC2cDkAjvgNxA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env&prettier=false&targets=&version=7.12.3&externalPlugins=. Let me see if I can add a specific pattern for these Babel forms only
I've implemented a fix for these style of reexport getters in https://github.com/nodejs/node/pull/35901.
So this was a decision to worsen the detection in the name of compatibility.
Well, a fix in the name of compatibility, which actually breaks the compatibility (previously worked code)…
Good that I discovered this problem right after the «fix» had been deployed and not at the migration to v.16 RTM.
@pubmikeb #35901 has landed on master with a fix for the issue you reported, it should be available in the next v15 release – and on nightly builds until then. I'm going to close this now, please reopen if you find another bug.
Thank you for being vigilant, it's kinda cool this compatibility bug was fixed before an actual release of Node.js 👍