graphql-nexus / nexus

Code-First, Type-Safe, GraphQL Schema Construction
https://nexusjs.org
MIT License
3.4k stars 274 forks source link

How to configure `tsconfig.json` to use Next.js together with Nexus? #391

Open nikolasburk opened 4 years ago

nikolasburk commented 4 years ago

I have an example that combines GraphQL Nexus with Next.js, you can find it here: https://github.com/prisma/prisma-examples/tree/prisma2/typescript/graphql-nextjs

Now, I'm trying to invoke the Nexus generation via:

ts-node --transpile-only pages/api

Here is my makeSchema:

export const schema = makeSchema({
  types: [Query, Mutation, Post, User, GQLDate],
  outputs: {
    typegen: path.join(__dirname, 'nexus-typegen.ts'),
    schema: path.join(__dirname, 'schema.graphql')
  },
})

So, I'd expect that the Nexus generation outputs the two files nexus-typegen.ts and schema.graphql.

However, when I run the command I see this error:

$ npm run generate:nexus
> hello-next@1.0.0 generate:nexus /Users/nikolasburk/prisma/github/prisma-examples/typescript/graphql-nextjs
> ts-node --transpile-only pages/api
/Users/nikolasburk/prisma/github/prisma-examples/typescript/graphql-nextjs/pages/api/index.ts:1
import { idArg, makeSchema, objectType, stringArg, asNexusMethod } from 'nexus';
       ^
SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:703:23)
    at Module.m._compile (/Users/nikolasburk/.config/yarn/global/node_modules/ts-node/src/index.ts:493:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:770:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/nikolasburk/.config/yarn/global/node_modules/ts-node/src/index.ts:496:12)
    at Module.load (internal/modules/cjs/loader.js:628:32)
    at Function.Module._load (internal/modules/cjs/loader.js:555:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:822:10)
    at Object.<anonymous> (/Users/nikolasburk/.config/yarn/global/node_modules/ts-node/src/bin.ts:158:12)
    at Module._compile (internal/modules/cjs/loader.js:759:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! hello-next@1.0.0 generate:nexus: `ts-node --transpile-only pages/api`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the hello-next@1.0.0 generate:nexus script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/nikolasburk/.npm/_logs/2020-02-28T16_13_47_524Z-debug.log

I was able to fix the error with the help of this SO question, I needed to adjust the module in the compilerOptions of my tsconfig.json from esnext to commonjs to make this work.

However, when starting my Next.js app again, it autommatically overrides that setting to esnext again:

$ npm run dev

> hello-next@1.0.0 dev /Users/nikolasburk/prisma/github/prisma-examples/typescript/graphql-nextjs
> next

[ wait ]  starting the development server ...
[ info ]  waiting on http://localhost:3000 ...
The following changes are being made to your tsconfig.json file:
  - compilerOptions.target to be suggested value: es5 (this can be changed)
  - compilerOptions.module must be esnext (for dynamic import() support)

[ info ]  bundled successfully, waiting for typecheck results...
[ event ] build page: /next/dist/pages/_error
[ wait ]  compiling ...
[ info ]  bundled successfully, waiting for typecheck results...
[ ready ] compiled successfully - ready on http://localhost:3000

I'm wondering how I should configure my tsconfig.json to use both Nexus and Next.js together?

adnanfuat commented 4 years ago

same problem

JstnEdr commented 4 years ago

I had the same problem. I was able to get both nexus and nextjs working together by adding an additional config file that would be used by nexus. I called mine nexus.tsconfig.json. The problem is that Nextjs will always overwrite what's in tsconfig.json--just let nextjs do it's thing ;) You'll also need to update your package.json.

Add new config file nexus.tsconfig.json:

{
  "compilerOptions": {
    "sourceMap": true,
    "outDir": "dist",
    "strict": true,
    "lib": ["esnext"],
    "esModuleInterop": true
  }
}

Then update the script in your package.json to use the new config file:

...
scripts: {
   ...
    "generate:nexus": "ts-node --transpile-only -P nexus.tsconfig.json src/pages/api",
  ...
}
...

Related: https://github.com/zeit/next.js/issues/7361

Kingfapa commented 3 years ago

If anyone want to solve this without creating a separate tsconfig file, you can configure the root tsconfig with specific options for ts-node.

Add to tsconfig: "ts-node": { "compilerOptions": { "esModuleInterop": true, "target": "esnext", "module": "commonjs", "strict": true }, "transpileOnly": true }

Update generate command in package.json, for example: "generate:nexus": "ts-node pages/api"

deadcoder0904 commented 3 years ago

Is there any way to solve this if I use relative imports using @?

When I run

cross-env GENERATE=true cross-env DOTENV_CONFIG_PATH=.env.example ts-node --require dotenv/config --transpile-only -P nexus.tsconfig.json src/server/graphql/schema.ts

I get an error:

Error: Cannot find module '@/server/graphql/User'

The problem is then it finds all relative imports & keeps throwing error. This is a huge bummer for me. I don't want ugly absolute urls but can't get this thing to work. Any ideas?

I did try @Kingfapa's solution but it gives:

(node:12720) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension. (Use node --trace-warnings ... to show where the warning was created) SyntaxError: Cannot use import statement outside a module

How do I solve it?

My tsconfig.json looks like:

{
    "compilerOptions": {
        "target": "es5",
        "baseUrl": "node_modules",
        "paths": {
            "@/*": ["../src/*"]
        },
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve"
    },
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
    "exclude": ["node_modules", "cypress"]
}
deadcoder0904 commented 3 years ago

No worries solved it using tsconfig-paths :)

Had to change my run script to cross-env GENERATE=true cross-env DOTENV_CONFIG_PATH=.env.example ts-node -r tsconfig-paths/register --require dotenv/config --transpile-only -P nexus.tsconfig.json src/server/graphql/schema.ts & it worked.