Skip to content
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

Load codegen.ts in ESM projects #9086

Merged
merged 28 commits into from
Mar 7, 2023
Merged

Load codegen.ts in ESM projects #9086

merged 28 commits into from
Mar 7, 2023

Conversation

beerose
Copy link
Contributor

@beerose beerose commented Mar 1, 2023

Follow up PR: #9094

Description

This PR handles loading codegen.ts in projects using ESM. Some of the approaches I tried:

  • Changing cosmiconfig's configuration (nothing relevant that would make this work out of the box)
  • Registering TS with ts-node (I tried different configurations to be able to use await import)
  • Using eval: eval("import("pathname")"

I originally went with execSync(tsc ...) to compile the config file to CommonJS and cache the results. But the caching part has a bunch of edge cases so I took a different approach and used jiti to load the file.

See benchmarks ⏳

ESM path — tsc, cache miss:

➜  vite-react-ts git:(vite-configts-fix) ✗ time yarn codegen  
yarn run v1.22.19
$ graphql-codegen --config codegen.ts
✔ Parse Configuration
✔ Generate outputs
✨  Done in 7.46s.
yarn codegen  7.81s user 0.69s system 111% cpu 7.649 total

ESM path — tsc, cache hit:

➜  vite-react-ts git:(vite-configts-fix) ✗ time yarn codegen
yarn run v1.22.19
$ graphql-codegen --config codegen.ts
✔ Parse Configuration
✔ Generate outputs
✨  Done in 3.69s.
yarn codegen  3.22s user 0.38s system 92% cpu 3.896 total

ESM path — jiti:

➜  vite-react-ts git:(vite-configts-fix) ✗ time yarn codegen
yarn run v1.22.19
$ graphql-codegen --config codegen.ts
✔ Parse Configuration
✔ Generate outputs
✨  Done in 3.91s.
yarn codegen  3.33s user 0.36s system 90% cpu 4.094 total

.cts — jiti:

➜  vite-react-cts git:(vite-configts-fix) ✗ time yarn codegen
yarn run v1.22.19
$ graphql-codegen --config codegen.cts
✔ Parse Configuration
✔ Generate outputs
✨  Done in 3.36s.
yarn codegen  3.21s user 0.34s system 99% cpu 3.558 total

Non-ESM path:

➜  apollo-client git:(vite-configts-fix) ✗ time yarn codegen      
yarn run v1.22.19
$ graphql-codegen --config codegen.ts
✔ Parse Configuration
✔ Generate outputs
✨  Done in 3.92s.
yarn codegen  3.22s user 0.38s system 87% cpu 4.116 total

Some of the next steps are:

Related Closes #8509, Closes #8862, Closes #8809

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • Created a new example based on reproductions steps in the issue

Test Environment:

  • OS: macOS
  • NodeJS: 19.x

Checklist:

  • I have followed the CONTRIBUTING doc and the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@changeset-bot
Copy link

changeset-bot bot commented Mar 1, 2023

🦋 Changeset detected

Latest commit: f010b06

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@graphql-codegen/cli Patch
@graphql-cli/codegen Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2023

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@graphql-cli/codegen 3.0.4-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/cli 3.2.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/visitor-plugin-common 3.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/typescript-document-nodes 3.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/gql-tag-operations 2.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/typescript-operations 3.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/typescript-resolvers 3.1.1-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/typed-document-node 3.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/typescript 3.0.2-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/client-preset 2.1.1-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎
@graphql-codegen/graphql-modules-preset 3.1.1-alpha-20230307110723-f010b0664 npm ↗︎ unpkg ↗︎

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2023

💻 Website Preview

The latest changes are available as preview in: https://5d1dbded.graphql-code-generator.pages.dev

@beerose beerose marked this pull request as ready for review March 2, 2023 09:55
Copy link
Collaborator

@enisdenjo enisdenjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your code is very clean and easy to read - this looks great!

About the ESM detection, maybe I am too naive, but couldn't we just look for the import keyword in the config? We can use a regex for increased accuracy, something like import (.* from|"|').

Also, a test case for this would be great.

@beerose
Copy link
Contributor Author

beerose commented Mar 2, 2023

About the ESM detection, maybe I am too naive, but couldn't we just look for the import keyword in the config? We can use a regex for increased accuracy, something like import (.* from|"|').

Hmm, I'm not sure. You can have a TypeScript file with ESM syntax that technically is a CommonJS and can be required by ts-node. Notice that this bug only occurred with "type": "module" in package.json, and the workaround was to use .cjs instead of .ts for the config — link.

@enisdenjo
Copy link
Collaborator

Yes, you're right. But, it might make sense to immediately drop to tsc even on a hint, mainly for performance reasons (even if it would've worked with ts-node, it would with tsc too).

In future steps we might even drop ts-node altogether and programmatically use tsc with transpileModule.

Copy link
Collaborator

@enisdenjo enisdenjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me! I like that we dropped the cosmiconfig-typescript-loader especially.

We can go ahead and merge after the CI's all green.

// #8437: conflict with `graphql-config` also using TypeScriptLoader(), causing a double `ts-node` register.
const tsLoader = TypeScriptLoader({ transpileOnly: true });
return tsLoader(filepath, content);
const jiti = require('jiti')(__filename, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use import

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also do we bundle codegen cli to both cjs and Esm? If yes __filename will be not exist in esm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right. We do bundle to both. What's the best way to deal with it? Something like this:

import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url)

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@enisdenjo could we add banner with bob? Or should we bundle to Esm only instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beerose yeah but we need to add it only to ESM build 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saihaj, do you have any thoughts on that?

Copy link
Collaborator

@saihaj saihaj Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think script is fine for simplicity. We do similar thing too for binary. Ideally bob should have some hooks that we can use to call scripts as needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we do the same thing here?

if there is no other workaround..

Copy link
Contributor Author

@beerose beerose Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so it looks like we can workaround it by not providing __filename at all — jiti resolves it to process.cwd(), which I guess it's correct? https://github.com/unjs/jiti/blob/main/src/jiti.ts#L101

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the CI passes 😅

@dimaMachina
Copy link
Collaborator

This looks great to me! I like that we dropped the cosmiconfig-typescript-loader especially.

We can go ahead and merge after the CI's all green.

@enisdenjo I think we can remove ts-node too now?

@enisdenjo
Copy link
Collaborator

enisdenjo commented Mar 6, 2023

I think we can remove ts-node too now?

Yes sir! I think it was only necessary for cosmiconf.

@beerose
Copy link
Contributor Author

beerose commented Mar 6, 2023

I think we can remove ts-node too now?

Yes sir! I think it was only necessary for cosmiconf.

Is there any documentation that needs to be updated regarding this?

@saihaj
Copy link
Collaborator

saihaj commented Mar 6, 2023

I think we can remove ts-node too now?

Yes sir! I think it was only necessary for cosmiconf.

Is there any documentation that needs to be updated regarding this?

I think we are good here. ts-node already caused issues #8809 so I suppose now we also fixed issues for yarn pnp users

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants