GraphiQL 클라이언트를 사용하여 Nuxt 응용 프로그램 구현

지금까지 GraphiQL을 사용하는 프로젝트는 처음이라
UI 라이브러리에 의존하지 않는 설정 단계 등을 요약합니다.
그럼에도 이동할 장소가 필요해 Nuxt로 SSG 앱을 만들기로 했다.
Nuxt에 포함 사용@nuxtjs/compositon-api.
창고는 여기 있습니다.
https://github.com/sterashima78/nuxt-graphql-example

Nuxt 항목 설정


$ npx create-nuxt-app nuxt-graphql-example
Type Script, Universal 및 SSG를 적절하게 선택합니다.
composion-api를 사용하기 때문에 그것도 넣으세요.
https://composition-api.nuxtjs.org/getting-started/setup
평소에는 목록 구성을 수정하지만 어쨌든 여기까지입니다.
$ npm run dev

네.

GraphiQL 주변 설정


GiraphiQL 서버는 GiitHub의 GraphiQL API를 사용하기로 결정했습니다.
인증이 필요하거나 규모가 상당하기 때문에 충분히 놀 수 있다고 판단했다.

편집기 설정


VSCODE 를 사용합니다.
GraphiQL에 대한 질의를 작성할 때 보완 등을 할 수 있다.
GraphiQL 확장을 추가합니다.
나는 개인적으로 그것을 프로젝트의 추천 확장 기능에 넣고 설치 프로그램에 따라 조작하는 것을 좋아한다.
.vscode/extentions.json
{
  "recommendations": [
    "graphql.vscode-graphql"
  ]
}
구성 파일에 기록됩니다.
graphql.config.yml
schema: 
  - https://api.github.com/graphql:
      headers: 
        Authorization: "bearer ${GITHUB_PAT}"
documents: graphql/**/*.graphql
GITHUB_PAT는 GiitHub의 개인 방문 영패(PAT)입니다.
아래 내용을 참고하여 제작한다.
https://docs.github.com/ja/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql GITHUB_PAT는 환경 변수다..env에 기트 제출에 포함되지 않도록 쓰십시오.
.env
GITHUB_PAT=<ここにPATをかく>
이 확장자는 CodeLens에서 조회를 실행할 수 있을 것 같지만 환경 변수의 값을 볼 수 없어서 포기했습니다.
나는 간단한 조회를 써 보았다.다음 내용을 참고하여 쓰시오.
https://docs.github.com/en/graphql/reference/queries
graphql/vue.graphql
query vueRepository {
  repository(name: "vue", owner: "vuejs"){
    createdAt
  }
}
잘 보충하면 효과가 있다.

코드 생성 설정


유형 정보를 생성하려면 Type Script 항목입니다.
또한 질의에 대한 API 클라이언트를 생성하려면 이를 생성합니다.
저는 개인적으로 API 클라이언트와 응용 프로그램이 강하게 통합되는 것을 좋아하지 않기 때문에 얇은 클라이언트를 만들기로 결정했습니다.
GraphiQL Code Generatr를 사용합니다.
이하로 진행하다.
https://graphql-code-generator.com/docs/getting-started/installation
종속 패키지를 설치합니다.
$ npm i graphql
$ npm install --save-dev @graphql-codegen/cli
$ npm install --save-dev @graphql-codegen/typescript
설정은 graphql.config.yml에 쓰여 있습니다.
https://graphql-config.com/usage#extensions
graphql.config.yml
schema: 
  - https://api.github.com/graphql:
      headers: 
        Authorization: "bearer ${GITHUB_PAT}"
documents: graphql/**/*.graphql
extensions:
  codegen:
    generates:
      ./types/graphql.ts:
        plugins:
          - typescript
잠시 실행하다.
$ npx graphql-codegen -r dotenv/config
-r dotenv/config.env에 기재된 환경 변수를 해결하는 데 필수적이다.
graphiql schema의 형식 정보를 출력합니다.
types/graphql.ts
export type Maybe<T> = T | null;
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;



/** snip **/



/** A hovercard context with a message describing how the viewer is related. */
export type ViewerHovercardContext = HovercardContext & {
  __typename?: 'ViewerHovercardContext';
  /** A string describing this context */
  message: Scalars['String'];
  /** An octicon to accompany this context */
  octicon: Scalars['String'];
  /** Identifies the user who is related to this context. */
  viewer: User;
};
API 클라이언트도 생성됩니다.
플러그인 설치 등
$ npm i graphql-request
$ npm i -D @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request
설정 파일 수정
graphql.config.yml
schema: 
  - https://api.github.com/graphql:
      headers: 
        Authorization: "bearer ${GITHUB_PAT}"
documents: graphql/**/*.graphql
extensions:
  codegen:
    generates:
      ./infrastructure/graphql/generated-client.ts:
        plugins:
          - typescript
          - typescript-operations
          - typescript-graphql-request
코드 생성
$ npx graphql-codegen -r dotenv/config
실행해 보세요.
환경 변수를 읽을 매크로 패키지 추가
$ npm i dotenv
실행을 위한 스크립트 구현
infrastructure/graphql/index.ts
import { GraphQLClient } from 'graphql-request';
import { getSdk } from './generated-client';
import dotenv from "dotenv";
const { parsed: env } = dotenv.config()

async function main() {
  const client = new GraphQLClient('https://api.github.com/graphql', {
    headers: {
      Authorization: `bearer ${env?.GITHUB_PAT}`
    }
  });
  const sdk = getSdk(client);
  const { repository } = await sdk.vueRepository();

  console.log(`GraphQL data:`, repository);
}

main()
실행
$ npx ts-node ./infrastructure/graphql/index.ts
GraphQL data: { createdAt: '2013-07-29T03:24:51Z' }
생성된 코드에서 GraphiQL API에 요청할 수 있습니다.

응용 프로그램 포함


솔직히 사족감은 있지만 생성된 고객을 응용 프로그램에 편입시키고 싶어요.
여기서 다음 3개 Organization이 보유한 창고를 검색하는 앱을 만들고 싶습니다.(별다른 뜻은 없다)
  • https://github.com/vuejs
  • https://github.com/angular
  • https://github.com/sveltejs
  • 응용 프로그램에서 사용하는 형식 정의


    창고 이름, 지게소 수, 별표를 표시합니다.
    또한 API 클라이언트 유형과 API 클라이언트 주입을 위한 버튼도 준비되어 있습니다.
    domain/repository.ts
    import { InjectionKey } from "@nuxtjs/composition-api";
    export type Repository = {
      name: string;
      numOfIssues: number;
      numOfStars: number;
    }
    
    export type FetchRepositories = (group: string) => Promise<Repository[]>
    export const fetchRepositoriesInjectionKey: InjectionKey<FetchRepositories> = Symbol("FetchRepositories")
    

    GraphiQL 질의 작성


    운행 시간에 유형을 검사하기 위해 미리 포함 __typename.
    graphql/query.graphql
    query fetchRepositories($query: String!) {
      search(query: $query, type: REPOSITORY, first: 100) {
        nodes {
          ... on Repository {
            __typename
            name
            issues {
              totalCount
            }
            stargazers {
              totalCount
            }
          }
        }
      }
    }
    

    대상의 변환기 실현


    비록 유형이 있지만 나는 API의 실현을 응용 프로그램에 가져오는 것을 그리 좋아하지 않기 때문에 먼저 적당한 층에서 응용 프로그램의 유형으로 전환한다.
    infrastructure/graphql/converter.ts
    import { Repository } from '~/domain/repository'
    import { FetchRepositoriesQuery } from './generated-client'
    
    /**
     * Repository型
     */
    type FetchRepositoriesQueryNode = Exclude<
      FetchRepositoriesQuery['search']['nodes'],
      null | undefined
    >[0]
    type FetchRepositoriesQueryRepositoryNode = Extract<
      FetchRepositoriesQueryNode,
      { readonly __typename?: 'Repository' }
    >
    
    /**
     * Repository型のアサーション
     */
    export type IsRepositoryNode = (
      node: FetchRepositoriesQueryNode
    ) => node is FetchRepositoriesQueryRepositoryNode
    
    export const isRepositoryNode: IsRepositoryNode = (
      node
    ): node is FetchRepositoriesQueryRepositoryNode =>
      node?.__typename === 'Repository'
    
    /**
     * 変換関数
     */
    export type ConvertRepositoryFrom = (result: FetchRepositoriesQuery) => Repository[]
    export const convertRepositoryFrom: ConvertRepositoryFrom = (result) => {
      return result.search.nodes?.filter(isRepositoryNode).map((node) => ({
            name: node.name,
            numOfIssues: node.issues.totalCount,
            numOfStars: node.stargazers.totalCount,
          }))
        || []
    }
    
    
    공개할 고객은 깨끗한 대상으로 돌아갈 것이다.
    infrastructure/graphql/index.ts
    import { GraphQLClient } from 'graphql-request'
    import { getSdk } from './generated-client'
    import { FetchRepositories } from '~/domain/repository'
    import { convertRepositoryFrom } from './converter'
    
    export const fetchRepositoriesFactory = (pat: string): FetchRepositories => (
      group
    ) =>
      getSdk(
        new GraphQLClient('https://api.github.com/graphql', {
          headers: {
            Authorization: `bearer ${pat}`,
          },
        })
      )
        .fetchRepositories({ query: `org:${group}` })
        .then(convertRepositoryFrom)
    

    응용 프로그램에 포함


    나머지는 응용 프로그램에서만 사용할 수 있다.
    먼저 API 클라이언트를 provide 에서 inject 상태로 만듭니다.
    plugins/apiClient.ts
    import { onGlobalSetup, provide, defineNuxtPlugin } from '@nuxtjs/composition-api'
    import { fetchRepositoriesInjectionKey } from "~/domain/repository";
    import { fetchRepositoriesFactory } from "~/infrastructure/graphql/";
    export default defineNuxtPlugin(({ $config }) => {
      onGlobalSetup(() => {
        provide(fetchRepositoriesInjectionKey, fetchRepositoriesFactory($config.AUTH_TOKEN))
      })
    })
    
    PAT는runtimeConfig를 통해서당신에게전달됩니다.
    nuxt.config.js
    /* snip */
    
      privateRuntimeConfig: {
        AUTH_TOKEN: process.env.GITHUB_PAT
      },
      publicRuntimeConfig: {
        AUTH_TOKEN: process.env.NODE_ENV === "development" ? process.env.GITHUB_PAT : ""
      }
    
    /* snip */
    
    이후 각 페이지에서 데이터를 얻으면 된다.
    (태그 생략)
    pages/organization/_name.vue
    import {
      defineComponent,
      inject,
      useContext,
      useStatic,
      computed,
      ref,
    } from '@nuxtjs/composition-api'
    import { fetchRepositoriesInjectionKey } from '~/domain/repository'
    
    export default defineComponent({
      setup() {
        const fetchRepository = inject(fetchRepositoriesInjectionKey)
        if (!fetchRepository) {
          throw new Error('fetchRepositories is not injected')
        }
        const query = ref('')
        const { route } = useContext()
        const org = computed(() => route.value.params.name)
        const repositories = useStatic((org) => fetchRepository(org), org, 'org')
        return {
          repositories: computed(
            () =>
              (query.value === ''
                ? repositories.value
                : repositories.value?.filter((i) =>
                    i.name.includes(query.value)
                  )) || []
          ),
          query,
        }
      },
    })
    

    구성 작업 확인


    $ npm run generate
    $ npm start
    
    API에 대한 통신 없이 실행됩니다.

    끝말


    이 글은 GraphiQL 클라이언트를 사용하여 웹 전단 응용을 실현하였다.
    또 VSCODE의 확장 기능을 활용해 입력 완성을 유효하게 하고, GraphiQL Code Generator를 활용해 API 클라이언트를 생성했다.
    API 클라이언트를 Nuxt 응용 프로그램에 통합하여 정적 웹 사이트를 생성합니다.
    API를 구성 요소에 설치하지 않고 GraphiQL에서 다른 구성 요소로 설치할 경우 국부화에도 영향을 미칠 수 있습니다.
    GraphiQL은 필요한 정보만 얻을 수 있어 개발의 경험으로 매우 좋다고 생각합니다.
    다른 한편, 조회 API 목적에 강하게 의존하는 형식의 데이터를 반환했기 때문에 이 데이터를 구성 요소 내부로 가져오는 것을 피하는 것이 좋다.이것은 내가 처음 생각한 일이다.
    연기적인 문제도 쉽게 발생하기 때문에 필요에 따라 REST와 다른 실크로 전환할 수 있는 사전 제작이 중요하다고 생각합니다.

    좋은 웹페이지 즐겨찾기