NextJS 및 Graphql이 포함된 풀스택 웹 응용 프로그램

38367 단어

NextJS 및 Graphql이 포함된 풀스택 웹 응용 프로그램


ReactJS를 사용하여 프런트엔드 응용 프로그램을 개발하는 것에 대해 논의할 때 세 가지 주요 옵션을 찾을 수 있습니다.CRA, 단일 웹 응용 프로그램 구축에 전념하지만 CEO 포지셔닝에 어려움이 있습니다.Gatsby, 정적 사이트 생성에 전념, 뛰어난 성능, 멋진 CEO와 데이터 획득.그리고 우리는 NextJS을 가지고 있다. 내가 보기에 이것은 현재ReactJS 웹 응용 프로그램을 작성하는 가장 좋은 방식이다. 서버 쪽에서 보여주고 클라이언트를 선택할 수 있다. 멋진 내장 루트, 0 설정 이념이다. NextJS9로 인해 이 프레임워크는 API 루트를 제공했다. 이것은 매우 간단한 방식이고 우리의ReactJS 응용 프로그램에 백엔드를 제공할 수 있다. 우리는 본고에서 사용할 것이다.본고에서 우리는 API 루트에서 실행되는 GraphQL API를 어떻게 실현하는지 배울 것이다.

기본 NextJS 응용 프로그램


앞서 언급한 바와 같이 NextJS가 주목하는 것은 0 설정 이념이다. 우리는 쉽게 설정할 수 있지만 더욱 간단하기 위해서 우리는 터미널에서 npx create-next-app todo-app을 입력하면 사용할 수 있다.프로젝트 설정이 완료되면 cd todo-app을 입력하고 yarn dev을 입력하여 서버를 실행하고 모든 내용이 실행 중인지 확인합니다.

API 노선


차갑다우리는 현재nextjs 웹 프로그램을 시작하고 실행했습니다.pages/api/graphql.js이라는 새 파일을 만들고 다음 코드를 추가합니다.
export default (req, res) => {
  res.statusCode = 200

  res.send("GRAPHQL")
}
localhost:3000/api/graphql으로 이동하면 작성된 텍스트 GRAPHQL을 볼 수 있습니다.쉬웠어이제 GraphQL을 구성합시다!

GraphQL 설정


설치


우선, 우리는 apollo-server-micro을 작성하여 yarn add apollo-server-micro이라는 의존항을 추가한다

우리 모드


다음에graphql 컴파일 모드를 사용해야 합니다. 이것은 우리의 조회와 돌연변이, 데이터의 구조를 정의합니다.현재 hello이라는 검색을 원합니다. 문자열을 되돌려 줍니다.따라서 우리는 노선의 맨 위에 다음과 같은 내용을 추가합시다.
import { ApolloServer, gql } from 'apollo-server-micro'

const schema = gql`
  type Query {
    hello: String!
  }
`;

해상도


우리는 방금 모드를 작성했지만, 현재 GraphQL은 모드 해상도가 필요합니다. 이것은 GraphQL이 데이터를 어디서 얻는지 알려 줍니다.모드 아래에 해석 프로그램을 추가합니다.
const resolvers = {
  Query: {
    hello: (_parent, _args, _context) => "world!"
  }
}

서버


이제 모드와 해상도로 서버를 만듭니다.
const apolloServer = new ApolloServer({
  typeDefs: schema,
  resolvers,
  context: () => {
    return {}
  }
})
멋지다. 이 실례를 통해 우리는 모든 요청과 응답을 처리하는 처리 프로그램에 접근할 수 있다. 왜냐하면 우리는 실제로NextJS를 사용하고 있기 때문이다. 우리는 그것을 지정해야 한다. 우리의 요청에는 bodyParser이 필요하지 않다.
마지막 export default을 삭제하고 다음 내용으로 변경합니다.
const handler = apolloServer.createHandler({ path: "/api/graphql" });

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

export default handler;
알겠습니다. 현재 GraphQL 서버의 기본 설정이 있습니다. 왜 localhost:3000/api/graphql으로 넘어가지 않는지 확인하십시오!

하면, 만약, 만약...
query {
    hello
}
우리는 해상도의 회답을 받을 것이다.

CORS 회사


우리는 이 API를 전방에서 사용하기 위해 다른 일이 필요합니다. 따라서 yarn add micro-cors을 입력하여 새 패키지를 추가한 다음에 다음 내용을 추가합니다.
import  Cors  from  "micro-cors";  

const cors =  Cors({ 
    allowMethods:  ["POST",  "OPTIONS"]
});  

// Here is how we connect our handler with cors.
export default cors(handler);

Knex의 Postgres를 사용한 데이터입니다.


어느 정도에, 우리의 응용 프로그램은 데이터베이스에 어떤 접근을 해야만 일부 데이터를 오래 저장할 수 있다.그러기 위해서는 뭔가를 설치해야 합니다. 시작합시다!우선 yarn add knex pg으로 knex와 Postgres를 추가해 보도록 하겠습니다.
이제 데이터베이스 설정으로 knexfile.js이라는 파일을 만듭니다.
module.exports = {
  development: {
    client: "postgresql",
    connection: "postgres://postgres@localhost:5432/todo",
    migrations: {
      tableName: "knex_migrations"
    }
  },
};
다음은 첫 번째 마이그레이션을 만듭니다. Postgres에서 테이블을 만드는 방법을 알려 줍니다. yarn run knex migrate:make create_todo을 입력하는 것부터 migrations 폴더에 새 파일을 생성합니다. 테이블을 열고 원하는 방식을 추가합니다.
exports.up = function(knex) {
  return knex.schema.createTable("todos", function(table) {
    table.increments("id");
    table.string("description", 255).notNullable();
    table.boolean("done").defaultTo(false).notNullable();
  });
};

exports.down = function(knex) {
  return knex.schema.dropTable("todos");
};
우리 책상 하나 만들자!yarn run knex migrate:up 실행
코드에서 데이터베이스를 관리하는 데 도움을 줄 상수를 만들어야 합니다./pages/api/graphql.js을 열고 다음 내용을 추가합니다.
import knex from "knex";

const db = knex({
  client: "pg",
  connection: "postgres://postgres@localhost:5432/todo"
});

우리 모드 업데이트


쿨, 우리 이제 일할 수 있어.왜 우리는 패턴과 해상도를 바꾸지 않습니까?
const schema = gql`
  type Query {
    todos: [Todo]!
    todo(id: ID!): Todo
  }

  type Todo {
    id: ID!
    description: String!
    done: Boolean!
  }
`;

const resolvers = {
  Query: {
    todos: (_parent, _args, _context) => {
      return db
        .select("*")
        .from("todos")
        .orderBy("id")
    },
    todo: (_parent, { id }, _context) => {
      return db
        .select("*")
        .from("todos")
        .where({ id })
        .first()
    }
  }
}
만약 우리가 지금 localhost:3000/api/graphql으로 돌아간다면, 우리는 최종적으로 우리의 데이터를 얻고 사용할 수 있을 것이다!

근데 잠깐만...우리는 어떻게 데이터를 만들 것입니까?
좋아요.Mutation을 추가하는 방법을 보여 드리겠습니다. 이것은 데이터베이스에서 데이터를 만드는 데 도움을 줄 것입니다!

데이터 생성


우선, 우리는 모델에 새로운 유형을 추가해야 한다.이 예에서 우리는 먼저 돌연변이의 명칭 createTodo을 지정한 다음에 괄호 안에서 우리가 받을 값의 명칭과 유형을 지정해야 한다. 마지막으로 우리는 돌연변이가 무엇을 되돌려줄지 지정해야 한다. 이 예에서 Todo 유형이다.
const schema = gql`
  ...

  type Mutation {
    createTodo(description: String!, done: Boolean): Todo
    completeTodo(id: ID!): Todo
  }
`;
현재 resolvers 대상에 새로운 Mutation 키와 createTodo 키를 추가합니다
const resolvers = {
  ...

  Mutation: {
    createTodo: async (_, { description, done }, _c) => {
      return (await db("todos").insert({ description, done }).returning("*"))[0]
    },
    completeTodo: async (_, { id }, _c) => {
      return (await db("todos").select("*").where({ id }).update({ done: true }).returning("*"))[0];
    }
  }
}
이제 데이터베이스에서 TODO를 만들고 완성할 수 있습니다.


멋있는데 앞머리는요?

고객


지금까지 우리는 API 루트에서graphql를 통합하여 응용 프로그램의 서버 쪽을 구축해 왔는데 왜 응용 프로그램의 클라이언트를 통합하지 않습니까?

의존항


우선 GraphQL에 연결하는 데 필요한 두 개의 의존 항목을 추가합니다.yarn add @apollo/react-hooks apollo-boost

공급업체


우선 응용 프로그램의 Apollo 클라이언트를 설정합니다.이를 위해 pages/_app.js을 열고 다음을 추가합니다.
import '../styles/globals.css'
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient, { gql } from 'apollo-boost';


function MyApp({ Component, pageProps }) {
  const client = new ApolloClient({
    uri: "http://localhost:3000/api/graphql"
  })

  return (
    <ApolloProvider client={client}>
      <Component {...pageProps} />
    </ApolloProvider>
  )
}

export default MyApp

조회


이제 pages/index.js을 열고 필요한 내용을 가져오겠습니다.
import React, { useState } from 'react';
import { useQuery, useMutation } from "@apollo/react-hooks";
import { gql } from 'apollo-boost';
이제 GraphQL에서처럼 GraphQL 쿼리를 선언해야 합니다.
const GET_TODOS = gql`
  query {
    todos {
      id
      description
      done
    }
  }
`
현재 우리 구성 요소에서, 우리는 조회와 맵을 사용하여 응용 프로그램에서 그것들을 렌더링할 것이다
export default function Home() {
  const { loading, error, data, refetch } = useQuery(GET_TODOS);

  if(loading) return <p>Loading...</p>
  if(error) return <p>ERROR :(</p>

  return (
    <div>
      <h1>My TODO list</h1>

      {
        data.todos.map((todo) => (
          <div key={todo.id}>
            {todo.description}
            <button
              disabled={todo.done}
            >
              {todo.done ? "Done" : "Complete"}
            </button>
          </div>
        ))
      }

    </div>
  )
}
쿨, 이제 브라우저에서 우리가 해야 할 일을 볼 수 있을 거야.이제 TODO를 만드는 방법을 추가합니다.createTodo 돌연변이를 추가하는 것부터 시작하겠습니다.
const CREATE_TODO = gql`
  mutation CreateTodo($description: String!) {
    createTodo(description: $description) {
      id
      description
      done
    }
  }
`
이제 구성 요소에 상태 관리, 변이 및 양식을 추가하여 변이를 수행합니다. 결과는 다음과 같습니다.
export default function Home() {
  ...
  const [todo, setTodo] = useState("");
  const [createTodo] = useMutation(CREATE_TODO);

  const saveTodo = async (e) => {
    e.preventDefault();
    await createTodo({variables: { description: todo }});
    refetch();
    setTodo("")
  }

  ...

  return (
    <div>
      <h1>My TODO list</h1>

      <form onSubmit={saveTodo}>
        <label>
          New todo
          <input onChange={e => setTodo(e.target.value)} value={todo} />
        </label>
        <button type="submit">Save</button>
      </form>

      ...

    </div>
  )
}

대기사항 완료


아주 간단해!,왜 우리는 completeTodo의 변이를 추가하지 않고 단추에 기능을 추가합니까?
이것은 우리의 돌연변이 성명이다.
const COMPLETE_TODO = gql`
  mutation CompleteTodo($id: ID!) {
    completeTodo(id: $id) {
      id
    }
  }
`
우리의 구성 요소 중에는 다음과 같은 것들이 있다.
export default function Home() {
  const [todo, setTodo] = useState("");
  const { loading, error, data, refetch } = useQuery(GET_TODOS);
  const [createTodo] = useMutation(CREATE_TODO);
  const [completeTodo] = useMutation(COMPLETE_TODO)

  const saveTodo = async (e) => {
    e.preventDefault();
    await createTodo({variables: { description: todo }});
    refetch();
    setTodo("")
  }

  const onComplete = async (id) => {
    await completeTodo({variables: { id }});
    refetch();
  }


  if(loading) return <p>Loading...</p>
  if(error) return <p>ERROR :(</p>

  return (
    <div>
      <h1>My TODO list</h1>

      <form onSubmit={saveTodo}>
        <label>
          New todo
          <input onChange={e => setTodo(e.target.value)} value={todo} />
        </label>
        <button type="submit">Save</button>
      </form>

      {
        data.todos.map((todo) => (
          <div key={todo.id}>
            {todo.description}
            <button
              disabled={todo.done}
              onClick={() => onComplete(todo.id)}
            >
              {todo.done ? "Done" : "Complete"}
            </button>
          </div>
        ))
      }

    </div>
  )
}
만약 지금 우리가 브라우저에 들어간다면, 우리는 우리의 응용 프로그램이 실행 중인 것을 볼 수 있습니다!

결론


GraphQL은 지난 몇 년 동안 끊임없이 발전해 온 기술이며, NextJS도 마찬가지다.현재, 우리는 우리의 NextJS 응용 프로그램에서 API 루트를 사용할 수 있다. 우리는 그것들을 통합하여 사람을 즐겁게 하는 창고를 구축할 수 있고, 완전한 창고 웹 응용 프로그램을 하나의 전체로 할 수 있지만, 심지어는 서버가 없는 응용 프로그램을 실행할 수 있다🤔?
사진은 Alina Grubnyak에서 Unsplash으로 촬영되었다

좋은 웹페이지 즐겨찾기