Using Netlify functions to host a GraphQL API with a React frontend
Tags: netlify, graphql, react
Published: 2019-10-15 20:18:50

---
title: Using Netlify functions to host a GraphQL API with a React frontend
published: true
tags: netlify, graphql, react 
cover_image: https://arm.rbind.io/slides/img/netlify-landing.png
---

> This quick demo assumes you’re already familiar with Netlify as a deployment service, GraphQL as an API technology and React. 

The starting point was a normal React project created with `create-react-app`   then deployed on Netlify (you know…the usual)   
Then I arrived to the point where I found out I needed an API to do some backend-related stuff, I (innocently) reached out to create a new repository, wrote some GraphQL resolvers/mutations, committed the whole thing but just when I was looking for a _cheap_ vps to host it in, I stopped for a second then said to my self: why not do it on Netlify itself?

  > Narrator: he did not regret it.

The process was as straightforward as this:

1. I’ve started by *completely* moving the backend files from their separate repo to inside `src/` folder in the frontend repo:

    ![](https://api.monosnap.com/file/download?id=j5J4qHp6gAls2mbhHM7ZCJ1zFRitCt)

2. Then I’ve added  [netlify-lambda](https://github.com/netlify/netlify-lambda) as a dev dependency to the project; this is a tool created by the netlify team and provides a runtime for lambda functions. 

3. I did not have a `netlify.toml` file at the time so I created one, and updated the content with this:
    ```
    [build]
      command = "yarn build" # the command you run to build this file
      functions = "built-lambda" # netlify-lambda builds to this folder AND Netlify reads functions from here
      publish = "build" # create-react-app builds to this folder, Netlify should serve all these files statically


    // This helps the `netfliy-lambda` do its job and helps Netlify figuring out where to look for your functions when deployed. 
    // Note: the `functions` field will probably be different in your project depending on where you decided to put the GraphQL functions
    ```

4. The I’ve added two new scripts to my `package.json`:
			- `”start:lambda”:”netlify-lambda serve src/lambda”`
			- `”build:lambda”:”netlify-lambda build src/lambda”`

5. before going all lambda crazy, the backend repository was using a normal [apollo-server](https://github.com/apollographql/apollo-server) but now I needed to find a lambda compatible one, luckily [apollo-server-lambda ](https://www.npmjs.com/package/apollo-server-lambda) does exactly this and _barely_ required any changes on the existing files, the `graphql.js` looked like this:
    ```js
        const { ApolloServer } = require('apollo-server-lambda');

        const { typeDefs } = require('./lib/typeDefs');
        const { resolvers } =require('./lib/resolvers');

        const lambda = newApolloServer({
          typeDefs,
          resolvers,
          playground: true,
          introspection: true
        );

        exports.handler = lambda.createHandler({
          cors: {
            origin: '*',
            credentials: true
          }
        });
    ```

6. The last piece now was to wire the GraphQl client with the Netlify function: 
On the frontend, I’m working with `urql` so I had to update the client initialisation to this:
```js
  const client = createClient({
    url: process.env.NODE_ENV === 'development'
       ? 'http://localhost:9000/.netlify/functions/graphql'
       : '/.netlify/functions/graphql'
   })
```
The `http://localhost:9000/.netlify/functions/graphql` URL is the default one when running `npm run start:lambda` locally but when deploying to Netlify the functions are hosted on the same domain hence the check.   
> Note: This code is still valid for *your*  favorite GraphQL client too.

Now once I published  these new changes to Netlify, it detected that I’ve added a new function and did its magic:  
  ![](https://api.monosnap.com/file/download?id=ds8hZMWnKgZWO1alZSEvM4EPl5Wyc4)

## Couple of notes
* When working with databases, the standard approach of starting the database with the server does not work in this case since the lambda function is given a limited time to run on every request and will be shut down after the request is resolved, the solution is to open a database connection on every incoming request and cache it the between requests. I was able to do that (with `mongdb` in my case) using something like: 
```js
	let cachedDb
	if(cachedDb && cachedDb.serverConfig.isConnected()){
		context.db = cachedDb;
	} else {
		context.db = await connectDB();
		cachedDb = context.db;
	}
```	
 * You can simulate a full working Netlify runtime locally using their [Netlify Dev | Netlify](https://www.netlify.com/products/dev/) tool, this comes handy when you want to debug you full wired app locally.   

## Relevant Links
* Docs for Netlify functions:  [https://www.netlify.com/docs/functions/](https://www.netlify.com/docs/functions/) 
*  Netlify lambda: [https://github.com/netlify/netlify-lambda](https://github.com/netlify/netlify-lambda) 
* Apollo server lambda: [apollo-server/packages/apollo-server-lambda at master · apollographql/apollo-server](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-lambda)
* Netlify dev:  [Netlify Dev | Netlify](https://www.netlify.com/products/dev/)