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-importpackage 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:
- Design a GraphQL query (on the left)
- 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.
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.
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.
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.
Starting Up the Apollo Server
And now, this is how our backend/index.js file looks like:
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
After creating an instance of the Apollo Server and providing it our schema and resolvers we can now start up the server:
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
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.
Next, we need to connect Apollo Client to React. For that we will need to use the
ApolloProvider component exported from
ApolloProvider is similar to React's
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 that
ApolloProvider is hooked up, we can import
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
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.
As you can see I am exporting my query as a constant
GET_USERS, which I will later pass to the
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.
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! ☕️