-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ESM/CJS and deep imports #6606
Conversation
There were a few problems with #6580, which added ESM builds and deep imports to version-4. The `exports` section of `packages/server/package.json` had two mistakes: the `types` lines linked to files in the cjs directory but we only placed them in the esm directory, and the `types` lines are apparently supposed to appear first in each block. However, it turned out that this didn't matter because tsc doesn't even look in the `exports` section unless you set `moduleResolution` to `node16` or `nodenext` in your tsconfig `compilerOptions`, and we weren't! And it turns out doing that setting is a bit of a pain because many packages don't currently work with that flag. So if we published our package with the deep imports only listed in `exports` in package.json, we'd break any TypeScript user who's on the normal `moduleResolution: "node"` and telling them to set `nodenext` would be hard to obey. So since we want to continue to support tsc with `moduleResolution: "node"`, we have to teach tsc about our deep imports using the strategy of "spew a bunch of package.jsons around the package", not even under `src`/`dist`. Fortunately these package.json files can use paths starting with `../` in order to find the actual generated files. So for example, `standalone/package.json` tells tsc how to find `../dist/standalone/index.d.ts`, via fields like `types` and `main`. You might think that now that we have these little package.json files, the `exports` block would be completely redundant. Not so! Node itself does not support deep imports like `@apollo/server/standalone` by looking for a `main` in `standalone/package.json`: when importing from a published package name, it only looks for `main` at the top level of the package. So to support deep imports in Node we need the `exports` block! So this PR leaves both the `exports` block and the tree of `package.json`s in place, to be consumed by different software. We add some tsc use cases to the new smoke test. Note that it is not a goal of this PR to ensure that `moduleResolution: "nodenext"` works.
✅ Deploy Preview for apollo-server-docs ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit d289cec:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on this, seems like a pretty good outcome!
}, | ||
"./plugin/disabled": { | ||
"types": "./dist/esm/plugin/disabled.d.ts", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wanna make the index change here for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh it looks like you did make that file move so I think this needs an update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and maybe we need to smoke test these paths since presumably this is in a broken state without CI knowing.
There were a few problems with #6580, which added ESM builds and deep
imports to version-4.
The
exports
section ofpackages/server/package.json
had twomistakes: the
types
lines linked to files in the cjs directory but weonly placed them in the esm directory, and the
types
lines areapparently supposed to appear first in each block.
However, it turned out that this didn't matter because tsc doesn't even
look in the
exports
section unless you setmoduleResolution
tonode16
ornodenext
in your tsconfigcompilerOptions
, and weweren't! And it turns out doing that setting is a bit of a pain because
many packages don't currently work with that flag. So if we published
our package with the deep imports only listed in
exports
inpackage.json, we'd break any TypeScript user who's on the normal
moduleResolution: "node"
and telling them to setnodenext
would behard to obey.
So since we want to continue to support tsc with
moduleResolution: "node"
, we have to teach tsc about our deep imports using the strategyof "spew a bunch of package.jsons around the package", not even under
src
/dist
. Fortunately these package.json files can use pathsstarting with
../
in order to find the actual generated files. So forexample,
standalone/package.json
tells tsc how to find../dist/standalone/index.d.ts
, via fields liketypes
andmain
.You might think that now that we have these little package.json files,
the
exports
block would be completely redundant. Not so! Node itselfdoes not support deep imports like
@apollo/server/standalone
bylooking for a
main
instandalone/package.json
: when importing from apublished package name, it only looks for
main
at the top level of thepackage. So to support deep imports in Node we need the
exports
block!So this PR leaves both the
exports
block and the tree ofpackage.json
s in place, to be consumed by different software.We add some tsc use cases to the new smoke test.
Our smoke tests verify that consumers with
moduleResolution: "nodenext"
work (or at least, that they will work once ardatan/graphql-tools#4532 is released). However, our own builds don't work that way next because some of our test-only dependencies don't work with that flag.