express-graphql
express-graphql copied to clipboard
Support native ESM via .mjs.
Node.js natively supports ESM via .mjs
(currently behind the --experimental-modules
flag, soon to be unflagged).
At the moment, consumers using native ESM, graphql
and express-graphql
are in a conundrum (see https://github.com/graphql/express-graphql/issues/425). When they use graphql
the ESM .mjs
modules run. When express-graphql
internally uses graphql
, the CJS .js
files run. graphql
thinks there are multiple versions being used and throws a tantrum. This issue will be mitigated by supporting native ESM across both packages.
- Swapped deprecated
babel-preset-es2015
forbabel-preset-env
. - Added
package.json
engines
field. - Configured
babel-preset-env
to target the Node.js version defined inpackage.json
engines
field. - Kept Babel at v6, but moved config into a v7 ready
.babelrc.js
file for dynamic config via env. - Tidied the
package.json
scripts, added an ESM build step that generates.mjs
dist files. Follows the lead of https://github.com/graphql/graphql-js/pull/1244, although I do things quite different for my own projects with Babel v7. - Updated
package.json
main
field for ESM/CJS cross compatibility. - Added a
package.json
module
field for tree-shaking bundlers.
I didn't upgrade Babel to v7 to limit the scope of this PR. It would be a good idea though.
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.
If you have received this in error or have any questions, please contact us at [email protected]. Thanks!
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!
Don't merge yet, I'm noticing that dist/index.mjs
has a few erroneous module.exports
in it for some reason.
Looks great 🎉
Don't merge yet, I'm noticing that dist/index.mjs has a few erroneous module.exports in it for some reason.
Please ping me when you solve this issue or if you need help with it.
I was planning on doing 0.7.0
at the end of this week and would be great to also include this feature.
Tidied the package.json scripts, added an ESM build step that generates .mjs dist files. Follows the lead of graphql/graphql-js#1244, although I do things quite different for my own projects with Babel v7.
If you have time you can help to migrate graphql-js
: https://github.com/graphql/graphql-js/issues/1266
It would be ideal to first update it and than all other graphql/*
projects.
Added a package.json module field for tree-shaking bundlers.
Maybe it also make sense to add "sideEffects": false
simular to https://github.com/graphql/graphql-js/pull/1312
Added package.json engines field.
No need to support 4.0
since it's End-of-life
so you can set it to 6.0
https://github.com/nodejs/Release
As a breaking change, I updated the exports to be only named for ESM/CJS cross compatibility and consistency.
For a native ESM environment:
import { graphqlHTTP, getGraphQLParams } from 'express-graphql'
For a legacy CJS environment:
- const graphqlHTTP = require('express-graphql')
- const getGraphQLParams = graphqlHTTP.getGraphQLParams
+ const { graphqlHTTP, getGraphQLParams } = require('express-graphql')
The old way the additional getGraphQLParams
export was added onto the graphqlHTTP
function was pretty weird anyway, and now the import
and require
look consistent.
There is no concept of mixed default/named exports in CJS, only a babel convention of a .default
export. If we had mixed, this is what the API would look like:
// ESM:
import graphqlHTTP, { getGraphQLParams } from 'express-graphql'
// CJS:
const { default: graphqlHTTP, getGraphQLParams } = require('express-graphql')
As a breaking change, I updated the exports to be only named for ESM/CJS cross compatibility and consistency.
@jaydenseric I would prefer not make such breaking changes especially since the absolute majority of users don't use getGraphQLParams
function.
Can we make it backward compatible using babel-plugin-add-module-exports?
@IvanGoncharov
Can we make it backward compatible using babel-plugin-add-module-exports?
For starters, that plugin does not, and likely will not support babel v7.
The best way forward is to tweak the API to properly support both environments. As a best practice, no npm package should have mixed named/default exports. Only default, or only named. Only default is probably an inferior option if you expect your API to grow, as you can't export more stuff without a breaking change to named exports.
The new API would be consistent with graphql
and graphql-relay
, which only have named exports.
This issue is a dealbreaker for me and others I know. Because Apollo does not support native ESM either I've begun work on a new GraphQL server package.
(currently behind the --experimental-modules flag, soon to be unflagged).
Hi 👋 ! Node core and Node Module WG member here. There is no set date for when --experimental-modules
will be unflagged. There's also no guarantee that what has shipped now is what will be in the future. For example, there are several discussions in the Node Module WG on how to approach implementation. One such discussion is to ship a maximally minimal implementation that would require package-maps for resolving bare specifiers (no longer using the Node module resolution algorithm).
Adopting .mjs
with the idea that its current support is solid (for production use) at this stage is bit premature and may cause headache for users. Not only ecosystem hurdles like #425 or how Webpack locks down bundled .mjs
bits making your code more difficult to mock, stub, and spy. But also if/when changes do happen to Node's --experimental-modules
your ESM story will be various shades of broken.
The --experimental-modules
flag really does mean experimental. It's something you should pause and consider at least before going all in as the route for your ESM support strategy today.
Things were moving too slow so I published graphql-api-koa, and have been enjoying writing resolvers in native ESM for a month now without issue.
We're about a month away from Node 12 going into LTS. What happened to this feature?