📈

SolidJSでGraphQL扱いたいあなたへ…

2022/06/21に公開

SolidJS×GraphQL

SolidjsでGraphQLを扱う時の手順を紹介していこうと思います。

SolidJSプロジェクト作成する

degitを使ってテンプレートをダウンロードしてきます。

$ npx degit solidjs/templates/ts my-app
$ cd my-app
$ npm i

これだけですでにアプリが立ち上がってくるようになっています。

$ npm run dev

ブラウザで http://localhost:3000 でアクセスして画面が表示されればOKです。

GraphQL Code Generator

GraphQLのスキーマファイルからTypeScriptの型定義ファイルを生成するパッケージにGraphQL Code Generatorを利用します。

$ npm i graphql
$ npm i -D @graphql-codegen/cli

初期化します

$ npx graphql-codegen init

    Welcome to GraphQL Code Generator!
    Answer few questions and we will setup everything for you.

? What type of application are you building? (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
Application built with other framework or vanilla JS

? Where is your schema?: (path or url) (http://localhost:4000) 
schema.graphql

? Where are your operations and fragments?: (src/**/*.graphql) 
src/**/*.tsx

? Pick plugins: (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
TypeScript Operations (operations and fragments)

? Where to write the output: (src/generated/graphql.ts)
src/generated/graphql.d.ts

? Do you want to generate an introspection file?
Yes

? How to name the config file?
codegen.yml

? What script in package.json should run the codegen?
graphql-codegen

生成された codegen.yml を少し書き換えます

codegen.yml
overwrite: true
schema: "schema.graphql"
generates:
  src/generated/graphql.d.ts:
    plugins:
      - "typescript-operations"
  ./graphql.schema.json:
    plugins:
      - "introspection"

下記の内容で仮のスキーマファイルを作成します

schema.graphql
type Hello {
  message: String!
}

type Query {
  hello: Hello!
}

生成コマンドを実行します

$ npm run graphql-codegen

成功したらプロジェクト直下に graphql.schema.json というファイルが生成されていると思います。

@solid-primitives/graphql

SolidJSでGraphQLを簡単に扱うために@solid-primitives/graphqlを利用します。

npm i @solid-primitives/graphql

App.tsx でGraphQLのQuery文を書き加えます。

App.tsx
import type { Component } from "solid-js";
// 追加
import { gql } from "@solid-primitives/graphql";

import logo from "./logo.svg";
import styles from "./App.module.css";

// 追加
const helloQueryDocument = gql`
  query hello {
    hello {
      message
    }
  }
`;

const App: Component = () => {
  // 省略
};

export default App;

codegen.yml を書き換えます。

codegen.yml
overwrite: true
schema: "schema.graphql"
documents: "./src/**/*.tsx" // 追加
generates:
  src/generated/graphql.d.ts:
    plugins:
      - "typescript" // 追加
      - "typescript-operations"
  ./graphql.schema.json:
    plugins:
      - "introspection"

追加で必要になるパッケージのインストールします。

$ npm i -D @graphql-codegen/typescript

再度型定義ファイルを生成します。

$ npm run graphql-codegen

成功すると ./src/generated/graphql.d.ts が生成されています。

graphql.d.ts
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export type Hello = {
  __typename?: 'Hello';
  message: Scalars['String'];
};

export type Query = {
  __typename?: 'Query';
  hello: Hello;
};

export type HelloQueryVariables = Exact<{ [key: string]: never; }>;


export type HelloQuery = { __typename?: 'Query', hello: { __typename?: 'Hello', message: string } };

この型定義を使ってSolidJSのアプリからGraphQLを扱います。

App.tsx
import type { Component } from "solid-js";
// createGraphQLClientを追加
import { gql, createGraphQLClient } from "@solid-primitives/graphql";
// 追加
import { HelloQuery } from "./generated/graphql";

import logo from "./logo.svg";
import styles from "./App.module.css";

const helloQueryDocument = gql`
  query hello {
    hello {
      message
    }
  }
`;

const App: Component = () => {
  // 追加
  // GraphQLサーバのエンドポイント
  const newQuery = createGraphQLClient("http://localhost:8080/graphql");
  const [data] = newQuery<HelloQuery>(helloQueryDocument);

  return (
    <div class={styles.App}>
      <header class={styles.header}>
        <img src={logo} class={styles.logo} alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          class={styles.link}
          href="https://github.com/solidjs/solid"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn Solid
        </a>
        // 追加
        <div>{data()?.hello.message}</div>
      </header>
    </div>
  );
};

export default App;

ちなみに newQuery の返り値にはrefetchが返ってくるので、このコンポーネント内で同じAPIを叩きたい場合はこのrefetchを使うのが良かったりします。

まとめ

これでGraphQLサーバーに対してアクセスできるようになりました。
GraphQLCodeGeneratorでGraphQLスキーマから型定義ファイルを生成して、@solid-primitives/graphqlを使ってGraphQLを扱うという感じです。

GraphQLサーバーを立てるのはまた別記事で書こうと思います。(いつ書くかはわかりませんが…)
ではまた!!!

Discussion