Prisma + GraphQL. Project Setup Pt2 : Apollo Server & Client.

So, the first part concluded with deployment of Prisma, and now it’s time to set up the Apollo Server to run on the backend, and Apollo Client on the FrontEnd.

Setting Up Apollo Server 2

Let’s start with installing the required dependencies. We’re going to run the npm install command from our backend folder.

npm i apollo-server graphql graphql-import prisma-binding
  • apollo-server — the core library for the server itself.
  • graphql — so that we can build our queries and mutations
  • grapql-import - in case if you decide to split your schema definition into multiple files, graphql-import package is there to help you importing & exporting schema definitions in GraphQL SDL (a.k.a GraphQL modules). It is also important to notice that it currently uses a custom syntax based on SDL comments.

Prisma bindings vs Prisma client

What are GraphQL Bindings?

GraphQL bindings are functions in your programming language that let you send queries, mutations and subscriptions to a GraphQL API. The functions are generated based on a GraphQL schema and mirror the GraphQL API.

Essentially, GraphQL bindings:

  • enable accessing a GrapQL API from a variety of programming languages;
  • provide a “GraphQL ORM” layer, which interfaces with your Prisma through a simplified resolvers.
  • You can read more about it here.

To understand it better we can refer to the image below:

  1. Design a GraphQL query (on the left)
  2. Implement the resolvers, which will in turn construct corresponding queries to the Prisma API using GraphQL bindings (on the right).

How does code generation work with GraphQL bindings? The Prisma GraphQL bindings are generated based on the Prisma data model.

FAQ

The Prisma client and Prisma bindings both provide ways to interact with the Prisma server that sits on top of your database and therefore allow you to read and write data in your database. It is generally recommended to use the Prisma client. Prisma bindings can be used for advanced use cases when building GraphQL servers.

This time we’re gonna use prisma-binding to build our GraphQL server.

When we use the prisma-binding, the info object that's received by your GraphQL resolvers is passed down to the Prisma API using Prisma bindings. Also, prisma-binding API mirrors the Prisma GraphQL API.

Build a schema — create the blueprint for your data graph

GraphQL schema defines what types of data a client can read and write to your data graph. Schemas are strongly typed.

Essentially, your schema’s structure supports the actions that your clients will take, and in this example we can have a list of users, and we can create a user.

Our schema needs to define queries that clients can execute against the data graph in order to fetch the data, and mutations enable clients to modify the data.

Below is an example of our simple schema.

src/schema.graphql

On the first line, we are importing prisma.graphql (which we generated in the previous post), our Prisma API essentially. But it is inaccessible from the server side unless we import it into our schema.

Now that we’re done with the schema definition let’s move on to defining our resolvers.

Resolvers tell Apollo Server how to fetch the data associated with a particular type in your schema.graphql.

In short, resolvers implement the API.

Query.js (Query resolvers) Example

To learn about the resolver’s arguments check out this page.

The Query resolver corresponds to the Query type defined in your schema.

Using this simple resolver we can now fetch user by id.

src/Query.js

Mutation.js (Mutation resolver) Example

Same as the above, Mutation resolver corresponds to the Mutation type defined in your schema.

The code example enables the client to create new user.

src/Mutation.js

Starting Up the Apollo Server

And now, this is how our backend/index.js file looks like:

src/index.js

Now let’s talk about what is happening in our index.js file.

To recap quickly, since there are quite few files and it might get confusing. Define our datamodel.prisma → generate prisma.graphql → define our schema.graphql (it defines the server’s API) → import our schema on the line 3 above.

So, the code above imports the ApolloServer class from apollo-server, along with our schema from src/schema.graphql. It then creates a new instance of ApolloServer and passes it the imported schema via the typeDefs property.

After creating an instance of the Apollo Server and providing it our schema and resolvers we can now start up the server:

node index.js

Setting Up Apollo Client

Now moving on to the frontend. Again, let’s start with installing the required dependencies from the frontend folder.

Basically I just followed the instructions specified in the documentation.

npm install apollo-boost @apollo/react-hooks graphql
  • apollo-boost: Package containing everything you need to set up Apollo Client
  • @apollo/react-hooks: React hooks based view layer integration
  • graphql: Also parses your GraphQL queries

I am using create-react-app with Typescript, so in this case my app starts from App.tsx file. And in there I have imported ApolloClient from apollo-boost, and added the endpoint for our GraphQL server to the uri property of the client config object. This will enable our client to start fetching data.

App.tsx

Next, we need to connect Apollo Client to React. For that we will need to use the ApolloProvider component exported from @apollo/react-hooks. The ApolloProvider is similar to React's Context.Provider.

I am using React Router, so I’m gonna wrap my root route component with ApolloProvider, which will place the client on the context, hence allowing us to access it from any component in our component tree.

And now thatApolloProvider is hooked up, we can import useQuery and useMutation hooks available to us from @apollo/react-hooks. Now whenever we want to share our GraphQL data with our UI, we’re going to be using those hooks.

First, we pass our GraphQL query wrapped in the gql function into the useQuery hook. When your component renders and the useQuery hook runs, a result object will be returned containing loading, error, and data properties.

I actually created a separate graphql folder within the frontend folder, as I decided to keep all queries and mutations in there (for the sake of convenience), and so far in this example I have a file called user.query.ts.

graphql/user.query.ts

As you can see I am exporting my query as a constant GET_USERS, which I will later pass to the useQuery hook.

And now I’m gonna use GET_USERS in my root component and query for a list of all users in my database:

And that concludes the pt. 2 of the project setup, in which we have connected all the final pieces of our puzzle.

Afterwords

This is a very high-level overview of all those GraphQL and Prisma components, as I was rather focusing on the project setup. And now that you have the project up and running you can start digging deeper into the concepts, I tried to provide the links to all the resources I have come across while I was writing this post.

Good luck and have fun! ☕️

Everything is unknown until it’s known. Self-learner.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store