-
Notifications
You must be signed in to change notification settings - Fork 2k
Fix ESM/CJS and deep imports #6606
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
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!
| "require": "./dist/cjs/plugin/cacheControl/index.js" | ||
| }, | ||
| "./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
exportssection ofpackages/server/package.jsonhad twomistakes: the
typeslines linked to files in the cjs directory but weonly placed them in the esm directory, and the
typeslines 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
exportssection unless you setmoduleResolutiontonode16ornodenextin 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
exportsinpackage.json, we'd break any TypeScript user who's on the normal
moduleResolution: "node"and telling them to setnodenextwould 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.jsontells tsc how to find../dist/standalone/index.d.ts, via fields liketypesandmain.You might think that now that we have these little package.json files,
the
exportsblock would be completely redundant. Not so! Node itselfdoes not support deep imports like
@apollo/server/standalonebylooking for a
maininstandalone/package.json: when importing from apublished package name, it only looks for
mainat the top level of thepackage. So to support deep imports in Node we need the
exportsblock!So this PR leaves both the
exportsblock and the tree ofpackage.jsons 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.