Graphql-js: ESM named exports are not available with "type": "module"

Created on 25 Jul 2020  ·  8Comments  ·  Source: graphql/graphql-js

A package.json top-level field type with a value of module should make modules load as ES modules.

When I used that with graphql, I expected this to work (it didn't):

import { version } from "graphql"; // ❌ 

Importing from index.mjs works fine:

import { version } from "graphql/index.mjs"; // ✅ 

Shouldn't ESM named exports work out of the box when Node's package type is set to module?


Reproduce:

$ node -v
v14.6.0

$ echo '{ "name": "test", "version": "0.0.1", "type": "module" }' > package.json

$ npm i graphql
+ [email protected]

$ echo 'import { version } from "graphql"; console.log(version);' > test.js

$ node test.js
import { version } from "graphql"; console.log(version);
         ^^^^^^^
SyntaxError: The requested module 'graphql' 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 'graphql';
const { version } = pkg;
    at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21)
    at async ModuleJob.run (internal/modules/esm/module_job.js:137:5)
    at async Loader.import (internal/modules/esm/loader.js:162:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)

Most helpful comment

The way I resolved is to add

           {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false
                }
            },

to the [rules] section.

All 8 comments

Hey, @javascriptlabs.

It seems that the error message implies the graphql import hasn't been resolved to index.mjs, but to CommonJS build of the graphql module at node_modules/graphql/index.js:

SyntaxError: The requested module 'graphql' is expected to be of type CommonJS

I believe the issue is that while NodeJS treats your index.js as an ES module, it doesn't resolve the graphql import to its "module": "index.mjs" file. I'm searching NodeJS docs regarding this behavior, but cannot find it any mention that it would respect the module property of the package.json of the imported (third-party) module.

The module build file will work when you bundle your index.js with tools like webpack, as they respect the module field of GraphQL's package.json, and will include index.mjs instead of its CommonJS module.

hi @kettanaito looks like webpack 5 doesn't resolve it anymore. I'm getting this error:

ERROR in ../../../node_modules/graphql/index.mjs 25:0-49
Module not found: Error: Can't resolve './version' in 'node_modules\graphql'
Did you mean 'version.js'?
BREAKING CHANGE: The request './version' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ../../../node_modules/graphql/index.mjs 27:0-49
Module not found: Error: Can't resolve './graphql' in 'node_modules\graphql'
Did you mean 'graphql.js'?
BREAKING CHANGE: The request './graphql' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ../../../node_modules/graphql/index.mjs 29:0-40:50
Module not found: Error: Can't resolve './type' in 'node_modules\graphql'
Did you mean 'index.js'?
BREAKING CHANGE: The request './type' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ../../../node_modules/graphql/index.mjs 42:0-48:205
Module not found: Error: Can't resolve './language' in 'node_modules\graphql'
Did you mean 'index.js'?
BREAKING CHANGE: The request './language' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ../../../node_modules/graphql/index.mjs 50:0-122
Module not found: Error: Can't resolve './execution' in 'node_modules\graphql'
Did you mean 'index.js'?
BREAKING CHANGE: The request './execution' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

has happened to me as well when I removed yarn.lock and installed all modules from the scratch.
returning back yarn.lock solved the problem even though I updated webpack as
"webpack": "^5.2.0",
"webpack-cli": "^4.1.0"

I need to rebuild my package-lock.json file because I need packages to use @babel/runtime 7.12.5 instead of 7.11.2 to fix another webpack 5 issue.

Is there another temporary solution to get webpack 5 to resolve graphql imports @kettanaito ?
I tried adding fullySpecified: false to test: /\.tsx?$/, which fixes the error Error: Can't resolve './graphql', but I'm still getting Error: Can't resolve './version' in '/home/dori/Projects/Work/Project/v3/client/node_modules/graphql'

The way I resolved is to add

           {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false
                }
            },

to the [rules] section.

I have the same issue and using the solution from @flyandi did not work for me. Webpack 5.7.0.

I have the same issue and using the solution from @flyandi did not work for me. Webpack 5.7.0.

In addition to that rule I think your resolve section also needs to look like this:
resolve: { extensions: ['.wasm', '.mjs', '.js', '.jsx', '.json'] },

I have the same issue and using the solution from @flyandi did not work for me. Webpack 5.7.0.

In addition to that rule I think your resolve section also needs to look like this:
resolve: { extensions: ['.wasm', '.mjs', '.js', '.jsx', '.json'] },

This didn't work for me either. Only thing that has worked is to add the extensions. That is, in index.mjs, I have to change
from './error'
to
from './error/index.js'

It just bit me again. Quite a drag.

Was this page helpful?
0 / 5 - 0 ratings