概要
やり方
1. 必要なパッケージをインストール
yarn add apollo-server-micro graphql micro next@latest react@latest react-dom@latest
yarn add -D typescript @types/react
2. テキトーにメインページを作る
pages/index.tsx
を作り、テキトーにメインページを立ちあげる。拡張子をtsxにしておくと、Next.js 9は勝手にTypescriptのtsconfig.jsonを用意してくれる。
速さ⚡️を求めるならば、tsconfig.json
を書く前に、サーバーを立ち上げる。
テキトーなメインページの例👇
export default ()=>(
<p>ほげ</p>
)
Reactのコンポーネントをexport default
すればそれが配信される。画像などのファイルは/static
配下に単に配置すれば配信される。
サーバー立ち上げ
yarn next
初回のターミナルのログの例
~/W/next9 graphql ❯❯❯ yarn next
yarn run v1.15.2
warning package.json: No license field
$ '/███████████/██████████/next9 graphql/node_modules/.bin/next'
[ wait ] starting the development server ...
[ info ] waiting on http://localhost:3000 ...
We detected TypeScript in your project and created a tsconfig.json file for you.
Your tsconfig.json has been populated with default values.
[ info ] bundled successfully, waiting for typecheck results ...
[ ready ] compiled successfully (ready on http://localhost:3000)
※ Next.js 9からサーバーでプレレンダリングできていると、右下に⚡️マークがつくようになりました。
3. テキトーにGraphQLサーバーを作る
/pages/api
配下にはAPIのエンドポイントを生やせる。GraphQLのモックサーバを立てよう。
import { ApolloServer, gql } from 'apollo-server-micro';
// ここからGraphQLのモックの定義
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'world',
},
};
const apolloServer = new ApolloServer({ typeDefs, resolvers });
// ここから先はNext.jsが読みに行く領域
export default apolloServer.createHandler({path:"/api"});
export const config = {
api: {
bodyParser: false,
},
};
サーバー再起動するまでもなく、APIが立ち上がる。
💃🕺嬉しい💃🕺
ここから、ApolloClientを入れるなり、モックじゃないGraphQLサーバーをこしらえるなりすると良い。
終わり
ポイント
tsconfig書く前に、サーバー立ち上げてしまおう。
Next.js 9からは、tsx
をNext.jsが見えるどこかにおけば、勝手に以下のtsconfig.json
が用意されてしまう。tsc --init
したのが書き変わるのでさっさと立ち上げたいなら、next
を先にする方が早い。
短絡的に言えば、pages/index.tsx
書けばオッケー。
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}
apollo-serverはmicro用のやつを使う。
pages/api
配下で (req, res)を受け取る関数をexport default
すれば、APIサーバが立つという寸法。
export default (req, res) => {
res.setHeader('Content-Type', 'application/json')
res.statusCode = 200
res.end(JSON.stringify({ name: 'Nextjs' }))
}
デフォルトのres,req(ただし幾らかミドルウェアが入っている)をいじるより、Zeit▲のmicroでマイクロサービスを/pages/api
にもさもさ生やせば、賑やかになると思う。これはご機嫌。
参考:next.js/examples/api-routes-micro/
ということで、apollo-server-ナンチャラ
は、apollo-server-micro
を使うっぽいなあってのは、API Routeの見た目にわかった。しかし、GraphQLサーバを立たせるに当たって2点ハマりポイントがあった。
ハマり1. graphQLサーバのパスをちゃんと指定する。
apollo-server
はデフォルトでlocalhost:3000/graphql
にサーバーを立たせようとする。
一方で、Next.js 9はAPIを単純な設定ならばlocalhost:3000/api
配下にしか生やせない。したがって、apollo-server-micro
のcreateHandler
にオプションを指定する。
const apolloServer = new ApolloServer({ typeDefs, resolvers });
const handler = apolloServer.createHandler({path:"/api"});
このhandler
をexport default
すれば、graphQLサーバが立つもんだと思ったらそうはいかない。
ハマり2. export const config={option}ちゃんとする
export default handler;
したところでGraphQL Playground
が動いているので、見た感じAPIが機能しているように思えるが、スキーマをダウンロードできない、クエリを投げられないで、まともに動いていない。
これは、Next.js 9
が自動で設定しているbodyParser
が原因らしい。数時間時間を潰してしまった。
Next.js 9
のAPI routesは備え付けで少しのミドルウェア(cokkieやquery、bodyをreqに生やすことができるやつ)が入っており、その中で、bodyParser
はデフォルトでonであり、req
をパースしてしまう。
しかし、API配下で、Next.js 9
に設定を伝える方法があるのでこのようにすると、クエリも投げられるし、スキーマもダウンロードできるようになる。以下のconfigは決め打ちで。
export default apolloServer.createHandler({path:"/api"});
export const config = {
api: {
bodyParser: false,
},
};
参考 next.js/examples/api-routes-graphql/
まとめ
- 恐ろしく楽チンにNextのサーバーとGraphQLのサーバを立てられるようになった。