sacchiのブログ

勉強したことを中心に書きます

Next.jsのAPI RoutesにGraphQLサーバーをたてる

この記事は

前提として私は夏休みに入るまでフロントエンド超初心者でした。そして夏休みを経て初心者に成長しました。

超初心者だったときにVue.js+Firebase(FirestoreとかAuthenticationとか)でサーバーレスなWebアプリをせっせとつくっていたのですが、最近色々学んだ結果、Next.jsとGraphQLで綺麗にパフォーマンスをあげられそうな気がしてきたので、リプレイス計画をたてています。

具体的には以前つくったクソアプリ(当時は一生懸命つくったつもりでした...)には

  • ただのJSで書かれている
  • SSRで高速化できそうなところが多い
  • Firestoreのコレクションがネストしまっくっていてデータの取得のために何度もリクエストをしなくてはいけなかったり、無駄なデータをとってきてしまうことが多い(これがいちばんやだ)

などのクソ要素があります。 この記事はリプレイス計画の一環としてためした「Next.jsのAPI RoutesにGraphQLサーバーをたててみる」の備忘録です。

やっていく

apollo-server-microを使います。 Apollo Serverを名乗るものがたくさんいて困惑しましたが、ひとまず公式に従いました。 やっていくといっても実は公式がサンプルコードを用意してくれています。 なので、やることは以下のステップだけ。

  1. Next.jsのプロジェクトを作成
  2. src/pages/api/graphql.tsにサンプルコードを真似する

お試しなのでダミーデータをベタ書きで持つようにしています。

import { ApolloServer, gql } from "apollo-server-micro";

const typeDefs = gql`
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`;

const books = [
  {
    title: "Harry Potter and the Chamber of Secrets",
    author: "J.K. Rowling",
  },
  {
    title: "Jurassic Park",
    author: "Michael Crichton",
  },
];

const resolvers = {
  Query: {
    books: () => books,
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

export const config = {
  api: {
    bodyParser: false,
  },
}

export default server.createHandler({ path: "/api/graphql" })

bodyParser: false だけ謎だったのですが、Node.js入門によると、HTTP リクエストのボディ部を読み込み、 req.body にパース (文字列の解析) した結果を設定します。 らしいので、パースせずにそのまま描画したい、、みたいな感じなのでしょうか?

この設定をなくすとPlaygroundで結果が表示されなくなったので、とても大事ということだけわかった()

  1. npx next dev すると

http://localhost:3000/api/graphql にPlaygroundがたちあがる🎉

f:id:hcp-miyuki:20210927211539p:plain

お困りごと

バージョンを指定せずにapollo-server-microをインストールすると、最近版の3.3.0が入ります。 ただ、3系だと2つのエラーに悩まされたので、最終的に一番ダウンロード数が多かった2.25.2を入れ直しました。

エラー1 UnhandledPromiseRejectionWarning: Error: You must `await server.start()` before calling `server.applyMiddleware()` at ApolloServer

これはエラーというよりは3系からこういう仕様になったらしいです。 なので落ち着いて言われたとおりに対応しました。また、Apollo Server v3のドキュメントにも書かれていました。

エラー2 Apollo Server network error: unable to reach server

エラー1を倒したらなんか出てきた...なんとなく、CORS周りな気がします。ブラウザ変えると直るよ!みたいな曖昧なことがstackoverflowに回答として書かれていたのを見て、「疲れたし、公式も2系だからダウングレードするか...」と妥協してしまいました。

おわりに

たいしたことはしていないけど、GraphQLやNext.jsなど、2ヶ月前には全然わかっていなかったことが少しわかっていることに感動しています。 つぎはFirestoreの読み書きの記事を書きたいな〜