한번에 Nuxt.제이스와 아폴로로 GraphiQL 분위기를 잡은 하슨.
본문의 목적
Nuxt.제이스와 아폴로 클라이언트의 손잡이를 사용해 그래픽QL의 분위기를 잡기 위해서다.
백엔드는 Pokemon API를 사용합니다.
드디어 다음 포켓몬 도감을 완성했습니다.
(Deploy 작업과 관련되지 않음)
https://nuxt-graphql-demo.netlify.app/
개발 환경
GraphiQL 소개
개발을 시작하다
프로젝트 작성
npx create nuxt-app
명령을 사용하여 프로젝트를 만듭니다.
npx create-nuxt-app nuxt-graphql-example
대화형 Nuxt.js 프로그램을 시작할 수 있습니다.이번 선택은 다음과 같습니다.
Programming language는 타입(이하 TS)을 선택했지만, 이 앱에서는 금형을 사용하는 이점이 거의 없어 자바스크립트를 활용해 개발할 예정이다.
또한 UI 구축을 단순화하기 위해 Vuetify를 사용합니다.결과적으로 노동시간이 많이 줄었다.
? Programming language: TypeScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: Jest
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Continuous integration: None
? Version control system: Git
현재yarn dev
로컬 서버의 부팅을 확인할 수 있습니다.Apollo Client 설정
Apollo Client를 사용하여 GraphiQL이 있는 Request를 보냅니다.
라이브러리 설치
yarn add @nuxtjs/apollo graphql-tag
nuxt.config.js
에서client를 읽는 설정을 합니다.
// nuxt.config.js
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
'@nuxtjs/apollo',
],
// Apollo module configuration
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'https://graphql-pokemon2.vercel.app/',
}
}
},
TSgql.d.ts
에 대응하기 위해 새로 만들고 기술합니다.
// gql.d.ts
declare module '*.gql' {
import { DocumentNode } from 'graphql'
const content: DocumentNode
export default content
}
declare module '*.graphql' {
import { DocumentNode } from 'graphql'
const content: DocumentNode
export default content
}
실행할 질의 준비
프로젝트 아래에 새 디렉터리
apollo/queries
를 만들고 조회를 준비합니다.
├── apollo
│ └── queries
│ ├── pokemon.gql
│ └── pokemons.gql
$id:String!
String형에서 인자(Non-nullllable)
# pokemon.gql
query pokemon($id: String!) {
pokemon(id: $id) {
name
classification
types
resistant
weaknesses
evolutions {
name
id
image
}
evolutionRequirements {
name
amount
}
image
}
}
$amount:Int!
에서 얻은 포켓몬의 종류수는 반드시 Int형으로 수신해야 한다(Non-nulllable)
# pokemons.gql
query pokemons($amount: Int!) {
pokemons(first: $amount) {
id
name
image
}
}
UI 구축(pages)
pages
페이지 하이픈에 사용할 파일을 준비합니다.
├── pages
│ ├── index.vue
│ ├── pokemon
│ │ └── _id.vue
│ └── pokemons.vue
index.vue
사이트 설명 페이지.
취향에 맞게 맞춤 제작하세요.
<template>
<v-container fill-height>
<v-row justify="center" align-content="center" class="">
<v-col cols="12" align-self="auto">
<h1 class="text-center">This is the demosite by using Nuxt.js + GraphQL(Apollo)</h1>
</v-col>
<v-col cols="12" align-self="auto">
<h2 class="text-center">You can play the pokemomn picture book from sidebar menu</h2>
</v-col>
</v-row>
</v-container>
</template>
pokemons.gql
포켓몬스터
<script>
에서 apollo
object를 사용하면graphiQL의 Request를 진행할 수 있습니다.respponse
apollo
는 Object에서 발표한 pokemons
를 값으로 사용할 수 있습니다.
<template>
<v-container fluid>
<v-row dense>
<v-col v-for="pokemon in pokemons" :key="pokemon.id" :cols="12">
<v-card>
<NuxtLink :to="`pokemon/${pokemon.id}`">
<v-img
:src="pokemon.image"
class="white--text align-end"
gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.5)"
contain=true
height="800"
>
<v-card-title v-text="pokemon.name"></v-card-title>
</v-img>
</NuxtLink>
<!-- <v-card-actions>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>mdi-heart</v-icon>
</v-btn>
<v-btn icon>
<v-icon>mdi-bookmark</v-icon>
</v-btn>
<v-btn icon>
<v-icon>mdi-share-variant</v-icon>
</v-btn>
</v-card-actions> -->
</v-card>
</v-col>
</v-row>
<br>
<v-expansion-panels accordion>
<v-expansion-panel>
<v-expansion-panel-header>Show Query Result</v-expansion-panel-header>
<v-expansion-panel-content>
{{ pokemons }}
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</template>
<script>
import "vue-apollo";
import pokemons from "~/apollo/queries/pokemons.gql";
// pokemonは最大151匹
let numGetPokemons = 151;
export default {
data() {
return {
pokemons
};
},
// pokemon一覧を取得
apollo: {
pokemons: {
prefetch: "loading",
query: pokemons,
variables: {
amount: numGetPokemons
}
}
},
};
</script>
pokemon/_id.vue
포켓몬 일람페이지
NuxtLink
를 사용하여 포켓몬 상세 페이지를 동적으로 생성합니다.렌더링 시 리소스
pokemon
를 가져올 수 없어서 오류가 발생했습니다. v-if="pokemon"
완성되면 페이지가 표시됩니다.prefetch: ({ route }) => ({ id: route.params.id })
와 variables() {return { id: this.$route.params.id };}
를 사용하여 path내의 포켓몬 id를 획득하여 pokemon
조회의 변수로 사용합니다.※ 사용하는 구성 요소
singleExplanation
, multiExplanation
, evolutionExplanation
는 다음 장에서 설명합니다.
<template>
<div v-if="pokemon">
<v-container fluid>
<v-img
:src="pokemon.image"
class="white--text align-end"
gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.5)"
contain=true
height="800"
>
<v-card-title v-text="pokemon.name"></v-card-title>
</v-img>
<v-expansion-panels focusable>
<!-- classification -->
<single-explanation
referKey="Classification"
:referValue="pokemon.classification"
/>
<!-- types -->
<multi-explanation referKey="Types" :referValue="pokemon.types" />
<!-- resistant -->
<multi-explanation
referKey="Resistant"
:referValue="pokemon.resistant"
/>
<!-- weaknesses -->
<multi-explanation
referKey="Weaknesses"
:referValue="pokemon.weaknesses"
/>
<!-- evolutions -->
<evolution-explanation
v-if="pokemon.evolutions"
referKey="Evolutions"
:referValue="pokemon.evolutions"
/>
<!-- evolutionRequirements -->
<multi-explanation
v-if="pokemon.evolutionRequirements"
referKey="EvolutionRequirements"
:referValue="pokemon.evolutionRequirements"
/>
<!-- レスポンス -->
<v-expansion-panel>
<v-expansion-panel-header>Show Query Result</v-expansion-panel-header>
<v-expansion-panel-content class="justify-center">
{{ pokemon }}
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</div>
</template>
<script>
import pokemon from "~/apollo/queries/pokemon.gql";
import multiExplanation from "~/components/multiExplanation.vue";
import singleExplanation from "~/components/singleExplanation.vue";
import evolutionExplanation from "~/components/evolutionExplanation.vue";
export default {
apollo: {
pokemon: {
query: pokemon,
prefetch: ({ route }) => ({ id: route.params.id }),
variables() {
return { id: this.$route.params.id };
}
}
},
components: {
multiExplanation,
singleExplanation,
evolutionExplanation
}
};
</script>
UI 구성(components)
UI를 표시할 components를 만듭니다.
singleExplanation
, multiExplanation
, evolutionExplanation
구성 요소를 생성합니다.
├── components
│ ├── evolutionExplanation.vue
│ ├── multiExplanation.vue
│ └── singleExplanation.vue
singleExplanation
<template>
<v-expansion-panel>
<v-expansion-panel-header>{{ referKey }}</v-expansion-panel-header>
<v-expansion-panel-content class="text-center">
{{ referValue }}
</v-expansion-panel-content>
</v-expansion-panel>
</template>
<script>
export default {
props: ["referKey", "referValue"]
};
</script>
multiExplanation
<template>
<v-expansion-panel>
<v-expansion-panel-header>{{ referKey }}</v-expansion-panel-header>
<v-expansion-panel-content v-for="(value, key) in referValue" :key="key" class="text-center">
{{ value }}
</v-expansion-panel-content>
</v-expansion-panel>
</template>
<script>
export default {
props: ["referKey", "referValue"]
};
</script>
evolutionExplanation
NuxtLink
로 진화한 포켓몬 링크를 붙입니다.
<template>
<v-expansion-panel>
<v-expansion-panel-header>{{referKey}}</v-expansion-panel-header>
<v-expansion-panel-content v-for="(value, key) in referValue" :key="key" class="text-center">
<NuxtLink :to="`${value.id}`">
{{value.name}}
</NuxtLink>
</v-expansion-panel-content>
</v-expansion-panel>
</template>
<script>
export default {
props:[
'referKey',
'referValue'
]
};
</script>
UI 빌드(기타)
취향 변경
default.vue
에 따라 Sidebar의 항목과layout을 조정합니다
├── layouts
│ ├── default.vue
│ └── error.vue
<template>
<v-app dark>
<v-navigation-drawer
v-model="drawer"
:mini-variant="miniVariant"
:clipped="clipped"
fixed
app
>
<v-list>
<v-list-item
v-for="(item, i) in items"
:key="i"
:to="item.to"
:href="item.href"
router
exact
>
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="item.title" />
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar
:clipped-left="clipped"
fixed
app
>
<v-app-bar-nav-icon @click.stop="drawer = !drawer" />
<v-toolbar-title v-text="title" />
<v-spacer />
</v-app-bar>
<v-main>
<v-container>
<nuxt />
</v-container>
</v-main>
<v-footer
:absolute="!fixed"
app
>
<span>© {{ new Date().getFullYear() }}</span>
</v-footer>
</v-app>
</template>
<script>
export default {
data () {
return {
clipped: false,
drawer: false,
fixed: false,
items: [
{
icon: 'mdi-apps',
title: 'Welcome',
to: '/'
},
{
icon: 'mdi-format-list-bulleted',
title: 'Pokemons',
to: '/pokemons'
},
{
icon: 'mdi-code-tags',
title: ' Github',
href: 'https://github.com/kimkiyong0612/Nuxt-GraphQL-Demo'
}
],
miniVariant: false,
right: true,
rightDrawer: false,
title: 'Nuxt.js GraphQL(Pockemon API) Demo'
}
}
}
</script>
매듭을 짓다
지금까지 포켓몬 도감 제작이었습니다.
그리고 heroku와 Netlify를 디자인해 0엔에 사이트를 공개할 수 있다.
(Vercel에서 SSR의 Deploy가 순조롭게 진행되지 않았습니다. 성공한 사람이 있다면 저에게 알려주세요.)
수고하셨습니다.
Reference
Reference
이 문제에 관하여(한번에 Nuxt.제이스와 아폴로로 GraphiQL 분위기를 잡은 하슨.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kimkiyong/articles/b92b1029093741텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)