Serving nothing through GraphQL
Tags: graphql, apolloserver
Published: 2021-03-20 16:45:23

*The absolute minimal GraphQL server (with a hint of existential crisis)*

---

I was taking Apollo’s beginner-level [Odyssey interactive tutorials](https://odyssey.apollographql.com), having been trying and failing to learn GraphQL on and off over the last year. Midway through, I started wondering what *the most simple GraphQL server setup* looks like, so I made a server that returns *nothing*.

This is obviously not meant to be a pragmatic example. If you want to see basic Apollo Server examples with sensible defaults instead, go to:
- [Apollo Server CodeSandbox template](https://codesandbox.io/s/apollo-server-apollo-server) — fork it to get a live GraphQL server in 5 seconds
- https://github.com/apollographql/odyssey-lift-off-part1/tree/complete — the Apollo Odyssey course companion app
- [Official documentation “Getting Started” tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/)

## What do we need?
- Any Node.js app. I build mine locally on my machine from scratch, but you can use IDEs like Glitch or Codesandbox or use an existing project.
- If building locally, `node` and `npm` should be installed.
- How I made my app: 
	- Create the app directory and go there
	- Run `npm init`, go with all default values
	- (Optional) Install nodemon to monitor our app and auto-reload when the code changes:  `npm i --save-dev nodemon`
	- Open `package.json`, add `"start": "nodemon index.js localhost 4000"` to the `scripts`
- Create our main script file, eg. `index.js`. This is where we're going to write our server code. It can be called anything, eg. `app.js`. Make sure it matches the command in `package.json`. 
	- If using a template or adding to an existing app, open your `package.json` and see what the main script is called.

We are ready to set up the GraphQL server!

## Steps
1. Install dependencies and import functions
2. Create our type definitions schema
3. Create a new ApolloServer object
4. Start the server

### 1. Install dependencies and import functions

We need two packages as dependencies: `graphql` and `apollo-server`.
```bash
# Run in your app root directory
npm install apollo-server graphql
```

Then import `ApolloServer` and `gql` from `apollo-server` in our script file, eg. `index.js`. We're going to use them in the next steps.

```js
const { ApolloServer, gql } = require("apollo-server");
```

### 2. Create our type definitions schema

Next we create our **type definitions**, which describe the shape of the data our server will resolve and return. We write our definition as a string literal in a syntax called the GraphQL Schema Definition Language, then pass it to the template literal tag `gql` we imported in Step 1.

```js
const typeDefs = gql`
  # TODO add type definitions here
`;
```

There are multiple different of types, but here we simply define the `Query` type, where clients can query for `nothings`. This field shall return an array of string (it doesn't matter as I'm not planning to return anything—but it has to be defined), and it is nullable.

```js
const typeDefs = gql`
  type Query {
    nothings: [String]
  }
`;
```

Learn more:
- https://graphql.org/learn/schema/
- https://www.apollographql.com/docs/apollo-server/schema/schema/
- https://www.apollographql.com/docs/apollo-server/api/apollo-server/#gql
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

### 3. Create our server object

Now we instantiate the `ApolloServer` constructor class—ie. we create a new ApolloServer object—that takes an option object.

```js
const server = new ApolloServer({
  // TODO add options here
});
```

For this test app, we are passing one option from Step 2, `typeDefs`. You can see the complete list of options in the link below.

```js
const server = new ApolloServer({
  typeDefs, // shorthand for `typeDefs: typeDefs`
});
```

Learn more:
- https://www.apollographql.com/docs/apollo-server/api/apollo-server/#options

### 4. Start the server

Finally, we add the command to start our server.

```js
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});
```

Run `npm run start` to start our first GraphQL server. You will see something like this on your CLI console.

```
[nodemon] starting `node index.js localhost 4000`
🚀 Server ready at http://localhost:4000/
```

While our server is running, we can access the [GraphQL Playground](https://www.apollographql.com/docs/apollo-server/testing/graphql-playground/) on the server URL itself, in this case `localhost:4000`. It provides a quick, convenient graphical interface to interact with our server.

Write an opening `{` and press spacebar to open list of available fields. Here we only have one field, `nothings`.

![GraphQL Playground IDE showing a query input area with pop-up menu containing list of fields](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d99hfu53bj74nuq1blvl.png)

Once we have our query for `nothings`, press the "Run" icon, and our server returns the data (or lack thereof, in this case).

![GraphQL Playground IDE showing a query for nothings on the left column and the result of null on the right column](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnq07782iqgvt6vnqcz1.png)

That's it, we've got a server that serves nothing! 😁 Below is the full server code.

{% codesandbox nothing-apollo-server-pbrg9 module=/index.js %}

Learn more:
- https://www.apollographql.com/docs/apollo-server/api/apollo-server/#listen
- https://github.com/graphql/graphql-playground

## Random remarks

**Where are the resolvers?**

It's interesting that while we *have to* provide type definitions (the server won't run if we pass an empty option object or don't pass any argument), technically we don’t even need to pass resolvers in order to have a running GraphQL server 😮. (We do need to write resolvers to make a server that returns data, of course.)

Explanation: `resolvers` *is* required, but Apollo Server provides default resolvers if none is explicitly provided. When running at the top level as in our code here, it cannot look for anything from the parent and returns `null`—but that explains why we don't get an error despite not passing any resolver. See the logic: https://www.apollographql.com/docs/apollo-server/data/resolvers/#default-resolvers

**Phew, it’s regular JavaScript**

As someone who primarily works with frontend development and never built an API server before, to be honest I didn't know what it entailed—what languages and tools are necessary? This sample server demonstrates that it only requires intermediate-level vanilla JavaScript plus SDL for the type definitions. (I presume data retrieving and storing, deploying, CI/CD (etc) require knowledge of other languages and tools, but not for setting up the server itself.)

**What's next?**

I sure as heck don’t want to get stuck with a server that returns nothing 😆. Going to explore these next:
- Mocks
- Resolvers and data sources
- Deploying
- ?? ...and more

See you in the next posts!