{"id":316097,"date":"2020-07-06T07:52:32","date_gmt":"2020-07-06T14:52:32","guid":{"rendered":"https:\/\/css-tricks.com\/?p=316097"},"modified":"2020-07-07T07:49:09","modified_gmt":"2020-07-07T14:49:09","slug":"building-serverless-graphql-api-in-node-with-express-and-netlify","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/building-serverless-graphql-api-in-node-with-express-and-netlify\/","title":{"rendered":"Building Serverless GraphQL API in Node with Express and Netlify"},"content":{"rendered":"\n

I\u2019ve always wanted to build an API, but was scared away by just how complicated things looked. I\u2019d read a lot of tutorials that start with \u201cfirst, install this library and this library and this library\u201d without explaining why that was important. I\u2019m kind of a Luddite<\/a> when it comes to these things.<\/p>\n\n\n\n

Well, I recently rolled up my sleeves and got my hands dirty. I wanted to build and deploy a simple read-only API, and goshdarnit<\/em>, I wasn\u2019t going to let some scary dependency lists and fancy cutting-edge services stop me\u00b9<\/a>.<\/p>\n\n\n\n

What I discovered is that underneath many of the tutorials and projects out there is a small, easy-to-understand set of tools and techniques. In less than an hour and with only 30 lines of code, I believe anyone can write and deploy their very own read-only API. You don\u2019t have to be a senior full-stack engineer \u2014 a basic grasp of JavaScript and some experience with npm is all you need.<\/p>\n\n\n\n

At the end of this article you\u2019ll be able to deploy your very own API without the headache of managing a server. I\u2019ll list out each dependency and explain why we\u2019re incorporating it. I\u2019ll also give you an intro to some of the newer concepts involved, and provide links to resources to go deeper.<\/p>\n\n\n\n\n\n\n\n

Let\u2019s get started!<\/p>\n\n\n

A rundown of the API concepts<\/h3>\n\n\n

There are a couple of common ways to work with APIs. But let\u2019s begin by (super briefly) explaining what an API is all about: reading and updating data.<\/p>\n\n\n\n

Over the past 20 years, some standard ways to build APIs have emerged. REST (short for RE<\/strong>presentational S<\/strong>tate T<\/strong>ransfer) is one of the most common. To use a REST API, you make a call to a server through a URL \u2014 say api.example.com\/rest\/books<\/code> \u2014 and expect to get a list of books back in a format like JSON or XML. To get a single book, we\u2019d go back to the server at a URL \u2014 like api.example.com\/rest\/books\/123<\/code> \u2014 and expect the data for book #123. Adding a new book or updating a specific book\u2019s data means more trips to the server at similar, purpose-defined URLs.<\/p>\n\n\n\n

That\u2019s the basic idea of two concepts we\u2019ll be looking at here: GraphQL<\/strong> and Serverless<\/strong>.<\/p>\n\n\n

GraphQL<\/h4>\n\n\n

Applications that do a lot of getting and updating of data make a lot of API calls. Complicated software, like Twitter, might make hundreds of calls to get the data for a single page. Collecting the right data from a handful of URLs and formatting it can be a real headache. In 2012, Facebook developers starting looking for new ways to get and update data more efficiently.<\/p>\n\n\n\n

Their key insight was that for the most part, data in complicated applications has relationships<\/em> to other data. A user has followers, who are each users themselves, who each have their own followers, and those followers have tweets, which have replies from other users. Drawing the relationships between data results in a graph and that graph can help a server do a lot of clever work formatting and sending (or updating) data, and saving front-end developers time and frustration. Graph Query Language, aka GraphQL, was born.<\/p>\n\n\n\n

GraphQL is different from the REST API approach in its use of URLs and queries. To get a list of books from our API using GraphQL, we don\u2019t need to go to a specific URL (like our api.example.com\/graphql\/books example<\/code>). Instead, we call up the API at the top level \u2014 which would be api.example.com\/graphql<\/code> in our example \u2014 and tell it what kind of information we want back with a JSON object:<\/p>\n\n\n\n

{\n\u00a0 books {\n\u00a0 \u00a0 id\n\u00a0 \u00a0 title\n\u00a0 \u00a0 author\n\u00a0 }\n}<\/code><\/pre>\n\n\n\n

The server sees that request, formats our data, and sends it back in another JSON object:<\/p>\n\n\n\n

{\n\u00a0 \"books\" : [\n\u00a0 \u00a0 {\n\u00a0 \u00a0 \u00a0 \"id\" : 123\n\u00a0 \u00a0 \u00a0 \"title\" : \"The Greatest CSS Tricks Vol. I\"\n\u00a0 \u00a0 \u00a0 \"author\" : \"Chris Coyier\"\n\u00a0 \u00a0 }, {\n\u00a0 \u00a0 \u00a0 \/\/ ...\n\u00a0 \u00a0 }\n\u00a0 ]\n}<\/code><\/pre>\n\n\n\n

Sebastian Scholl compares GraphQL to REST<\/a> using a fictional cocktail party that makes the distinction super clear. The bottom line: GraphQL allows us to request the exact data we want while REST gives us a dump of everything at the URL.<\/p>\n\n\n

Concept 2: Serverless<\/h3>\n\n\n

Whenever I see the word \u201cserverless,\u201d I think of Chris Watterston\u2019s famous sticker.<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

Similarly, there is no such thing as a truly \u201cserverless\u201d application. Chris Coyier nice sums it up his \u201cServerless\u201d<\/a> post:<\/p>\n\n\n\n

What serverless is trying to mean, it seems to me, is a new way to manage and pay for servers. You don\u2019t buy individual servers. You don\u2019t manage them. You don\u2019t scale them. You don\u2019t balance them. You aren\u2019t really responsible for them. You just pay for what you use.<\/p><\/blockquote>\n\n\n\n

The serverless approach makes it easier to build and deploy back-end applications. It\u2019s especially easy for folks like me who don\u2019t have a background in back-end development. Rather than spend my time learning how to provision and maintain a server, I often hand the hard work off to someone (or even perhaps something) else.<\/p>\n\n\n\n

It\u2019s worth checking out the CSS-Tricks guide to all things serverless<\/a>. On the Ideas page<\/a>, there\u2019s even a link to a tutorial on building a serverless API<\/a>!<\/p>\n\n\n

Picking our tools<\/h3>\n\n\n

If you browse through that serverless guide you\u2019ll see there\u2019s no shortage of tools and resources to help us on our way to building an API. But exactly which ones we use requires some initial thought and planning. I\u2019m going to cover two specific tools that we\u2019ll use for our read-only API.<\/p>\n\n\n

Tool 1: NodeJS and Express<\/h4>\n\n\n

Again, I don\u2019t have much experience with back-end web development. But one of the few things I have encountered is Node.js. Many of you are probably aware of it and what it does, but it\u2019s essentially JavaScript that runs on a server instead of a web browser. Node.js is perfect for someone coming from the front-end development side of things because we can work directly in JavaScript \u2014 warts and all \u2014 without having to reach for some back-end language.<\/p>\n\n\n\n

Express is one of the most popular frameworks for Node.js. Back before React was king (How Do You Do, Fellow Kids?), Express was the go-to for building web applications. It does all sorts of handy thing like routing, templating, and error handling.<\/p>\n\n\n\n

I\u2019ll be honest: frameworks like Express intimidate me. But for a simple API, Express is extremely easy to use and understand. There\u2019s an official GraphQL helper for Express<\/a>, and a plug-and-play library for making a serverless application called serverless-http<\/a>. Neat, right?!<\/p>\n\n\n

Tool 2: Netlify functions<\/h4>\n\n\n

The idea of running an application without maintaining a server sounds too good to be true. But check this out: not only can you accomplish this feat of modern sorcery, you can do it for free<\/em>. Mind blowing.<\/p>\n\n\n\n

Netlify offers a free plan<\/a> with serverless functions that will give you up to 125,000 API calls in a month. Amazon offers a similar service called Lambda<\/a>. We\u2019ll stick with Netlify for this tutorial.<\/p>\n\n\n\n

Netlify includes Netlify Dev<\/a> which is a CLI for Netlify\u2019s platform. Essentially, it lets us run a simulation of our in a fully-featured production environment, all within the safety of our local machine. We can use it to build and test our serverless functions without needing to deploy them.<\/p>\n\n\n\n

At this point, I think it\u2019s worth noting that not everyone agrees that running Express in a serverless function is a good idea. As Paul Johnston explains<\/a>, if you’re building your functions for scale, it\u2019s best to break each piece of functionality out into its own single-purpose function. Using Express the way I have means that every time a request goes to the API, the whole Express server has to be booted up from scratch \u2014 not very efficient. Deploy to production at your own risk.<\/p>\n\n\n

Let\u2019s get building!<\/h3>\n\n\n

Now that we have out tools in place, we can kick off the project. Let\u2019s start by creating a new folder, navigating to fit in terminal, then running npm init<\/code>  on it. Once npm creates a package.json<\/code> file, we can install the dependencies we need. Those dependencies are:<\/p>\n\n\n\n

  1. Express<\/strong><\/li>
  2. GraphQL and express-graphql.<\/strong> These allow us to receive and respond to GraphQL requests.<\/li>
  3. Bodyparser.<\/strong> This is a small layer that translates the requests we get to and from JSON, which is what GraphQL expects.<\/li>
  4. Serverless-http.<\/strong> This serves as a wrapper for Express that makes sure our application can be used on a serverless platform, like Netlify.<\/li><\/ol>\n\n\n\n

    That\u2019s it! We can install them all in a single command:<\/p>\n\n\n\n

    npm i express express-graphql graphql body-parser serverless-http<\/code><\/pre>\n\n\n\n

    We also need to install Netlify Dev<\/a> as a global dependency so we can use it as a CLI:<\/p>\n\n\n\n

    npm i -g netlify-cli<\/code><\/pre>\n\n\n

    File structure<\/h3>\n\n\n

    There\u2019s a few files that are required for our API to work correctly. The first is netlify.toml<\/code> which should be created at the project\u2019s root directory. This is a configuration file to tell Netlify how to handle our project. Here\u2019s what we need in the file to define our startup command, our build command and where our serverless functions are located:<\/p>\n\n\n\n

    [build]\n\u2028\n\u00a0 # This command builds the site\n\u00a0 command = \"npm run build\"\n\u2028\n\u00a0 # This is the directory that will be deployed\n\u00a0 publish = \"build\"\n\u2028\n\u00a0 # This is where our functions are located\n\u00a0 functions = \"functions\"<\/code><\/pre>\n\n\n\n

    That functions<\/code> line is super important; it tells Netlify where we\u2019ll be putting our API code.<\/p>\n\n\n\n

    Next, let\u2019s create that \/functions<\/code> folder at the project\u2019s root, and create a new file inside it called api.js<\/code>.  Open it up and add the following lines to the top so our dependencies are available to use and are included in the build:<\/p>\n\n\n\n

    const express = require(\"express\");\nconst bodyParser = require(\"body-parser\");\nconst expressGraphQL = require(\"express-graphql\");\nconst serverless = require(\"serverless-http\");<\/code><\/pre>\n\n\n\n

    Setting up Express only takes a few lines of code. First, we\u2019ll initial Express and wrap it in the serverless-http<\/code> serverless function:<\/p>\n\n\n\n

    const app = express();\nmodule.exports.handler = serverless(app);<\/code><\/pre>\n\n\n\n

    These lines initialize Express, and wrap it in the serverless-http<\/code> function. module.exports.handler<\/code> lets Netlify know that our serverless function is the Express function.<\/p>\n\n\n\n

    Now let\u2019s configure Express itself:<\/p>\n\n\n\n

    app.use(bodyParser.json());\napp.use(\n\u00a0 \"\/\",\n\u00a0 expressGraphQL({\n\u00a0 \u00a0 graphiql: true\n\u00a0 })\n);<\/code><\/pre>\n\n\n\n

    These two declarations tell Express what middleware<\/strong> we\u2019re running. Middleware is what we want to happen between the request and response.<\/em> In our case, we want to parse JSON using bodyparser<\/code>, and handle it with express-graphql<\/code>. The graphiql:true configuration for express-graphql<\/code> will give us a nice user interface and playground for testing.<\/p>\n\n\n

    Defining the GraphQL schema<\/h3>\n\n\n

    In order to understand requests and format responses, GraphQL needs to know what our data looks like. If you\u2019ve worked with databases then you know that this kind of data blueprint is called a schema.<\/strong> GraphQL combines this well-defined schema with types<\/strong> \u2014 that is, definitions of different kinds of data \u2014 to work its magic.<\/p>\n\n\n\n

    The very first thing our schema needs is called a root query.<\/strong> This will handle any data requests coming in to our API. It\u2019s called a \u201croot\u201d query because it\u2019s accessed at the root of our API\u2014 say, api.example.com\/graphql<\/code>.<\/p>\n\n\n\n

    For this demonstration, we\u2019ll build a hello world example; the root query should result in a response of \u201cHello world.\u201d<\/p>\n\n\n\n

    Let\u2019s get those by adding this below the imports:<\/p>\n\n\n\n

    const {\n\u00a0 GraphQLSchema,\n\u00a0 GraphQLObjectType,\n\u00a0 GraphQLString\n} = require(\"graphql\");<\/code><\/pre>\n\n\n\n

    Then we\u2019ll define our schema like this:<\/p>\n\n\n\n

    const schema = new GraphQLSchema({\n\u00a0 query: new GraphQLObjectType({\n\u00a0 \u00a0 name: 'HelloWorld',\n\u00a0 \u00a0 fields: () => ({ \/* we'll put our response here *\/ })\n\u00a0 })\n})<\/code><\/pre>\n\n\n\n

    The first element in the object, with the key query<\/code>, tells GraphQL how to handle a root query. Its value is a GraphQL object with the following configuration:<\/p>\n\n\n\n

    So, our GraphQL API will need a schema (composed of types) for the root query. GraphQL provides some ready-built types, including a schema<\/code>, a generic object<\/code>\u00b2<\/a>, and a string<\/code>.<\/p>\n\n\n\n