Stéphane P. Péricat

Stéphane P. Péricat

Dec 7·5 min read

Vercel is one of the most popular serverless platforms nowadays, and for good reasons. Not only does it allow you to host your static web pages like other competitors out there, but it also allows you to setup serverless functions that you can invoke over HTTPS. This means that you can, for instance, set up a full blown Express application, create a RESTful API, microservices, etc...

I started wondering if it would be possible to setup a GraphQL server on Vercel.

In this tutorial, we will learn how to achieve this with Apollo and Express.

The demo code for this tutorial can be found here.

Pre-Requisites

This tutorial assumes that you:

  1. Signed up for a free Vercel account;
  2. Setup your version control provider (such as Github) to enable automatic deployments of your Vercel applications, and are familiar with importing projects;
  3. Have Node.js 14 or above installed on your local machine (and optionally, Yarn), along with a text editor (such as VS Code);
  4. Are familiar with basic GraphQL concepts.

Setting Up The Project

According to the Vercel documentation, all you need to do in order to setup serverless functions in your project is to create a folder called api at the root of your project. From there, any file located in that folder will be treated as a serverless function.

Let’s start by scaffolding a basic project structure. Type the following commands in your terminal:

# create the project folder, and navigate to it
mkdir apollo-server-vercel
cd apollo-server-vercel/
# create the `api` folder, and the server entry point
mkdir api
touch api/index.js
# create a basic package.json file
yarn init -y
# open the project in VS Code
code .

Let’s define the project type to module , so we can use ESM syntax. Open package.json , and add the following property:

"type" : "module"

Now, we can install some basic NPM packages:

yarn add express graphql cors apollo-server-express apollo-server-core

Implementing The Apollo Server

Open the api/index.js file, and import the necessary packages:

import { ApolloServer, gql } from "apollo-server-express";
import { ApolloServerPluginDrainHttpServer } from "apollo-server-core";
import http from "http";
import express from "express";
import cors from "cors";

Next, we’ll setup our Express app.

We need to add the CORS middleware, in order to allow a third party domain to query the server, and we also need to enable body data parsing by adding the JSON middleware, so that the Apollo server can interpret POST requests:

const app = express();app.use(cors());
app.use(express.json());
const httpServer = http.createServer(app);

Let’s define some very basic query and its matching resolver, to test that our Apollo server is working:

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

const resolvers = {
Query: {
hello: () => "world",
},
};

Now, we can create a method that will bootstrap our Apollo server, and attach it to our Express app as a simple middleware:

const startApolloServer = async(app, httpServer) => {
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

await server.start();
server.applyMiddleware({ app });
}

A few noticeable things in this code:

  1. We use the Apollo Server drain plugin, in order to add some useful functionalities to our Apollo server which are not available out of the box in the Express version of the module;
  2. The start() method of the Apollo server instance is asynchronous, which we handle with an await statement;
  3. Once the server is started, we can bind it to the Express app with the applyMiddleware() method.

Finally, we can invoke startApolloServer , and export the http server so that Vercel can start it:

startApolloServer(app, httpServer);

export default httpServer;

Configuring Route Rewriting

Last but not least, we need to configure some route rewrites to redirect any request to the /api folder in our project. To do so, create a file called vercel.json at the root of the project, and add the following configuration:

{
"rewrites": [{ "source": "/(.*)", "destination": "/api" }]
}

Deploying The Server To Vercel

You can now import your git project in your Vercel dashboard, and once it is deployed, you should see something like this:

The Apollo Server welcome page

And that’s it! We now have a fully functional GraphQL server hosted on Vercel. We can verify that it works by using Postman:

Postman call to test our GraphQL server

Extra Credit Assignment: Adding A Local Dev Environment

Now that we have our basic app and deployment pipeline set up, we might want to make it a bit easier for us to develop the server functionality on our local machine.

Let’s start by adding a couple of dev dependencies. Type the following command in your terminal:

yarn add -D nodemon consola dotenv

Nodemon will take care of restarting the server every time we save any change, and Consola is a nice logging utility we will use to let the developer know that the server is started. We also include Dotenv, in order to emulate the environment variables we might be using to store secrets in Vercel.

Let’s create a new file at the root of the project, call it dev.js , and add the following code to it:

import app from "./api/index.js";
import consola from "consola";
import dotenv from "dotenv";
dotenv.config();app.listen(3000, () => consola.info("Server started"));

We can also go ahead and create a .env file at the root of the project, which we will later use once we start adding environment variables.

Don’t forget to exclude your .env file from git by adding it to your .gitignore file!

Finally, we can add a new script to our package.json file to start the server with Nodemon:

"scripts": {
"dev": "nodemon dev"
}

Now, if you type yarn dev in your terminal, you should see this output:

$ nodemon dev
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node dev.js`
? Server started

Your server should now be available at http://localhost:3000/ . You will also have access to the Apollo Studio, to test your queries:

Apollo Server Studio

Conclusion

With a bit of configuration, it is fairly easy to setup a GraphQL server on Vercel; in a follow-up post, we will look at securing our API with authentication, and integrating it with third-party data providers.