DEV Community

Cover image for Serving nothing through GraphQL
Eka
Eka

Posted on • Updated on

Serving nothing through GraphQL

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


I was taking Apollo’s beginner-level Odyssey interactive tutorials, 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:

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.

# Run in your app root directory
npm install apollo-server graphql
Enter fullscreen mode Exit fullscreen mode

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.

const { ApolloServer, gql } = require("apollo-server");
Enter fullscreen mode Exit fullscreen mode

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.

const typeDefs = gql`
  # TODO add type definitions here
`;
Enter fullscreen mode Exit fullscreen mode

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.

const typeDefs = gql`
  type Query {
    nothings: [String]
  }
`;
Enter fullscreen mode Exit fullscreen mode

Learn more:

3. Create our server object

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

const server = new ApolloServer({
  // TODO add options here
});
Enter fullscreen mode Exit fullscreen mode

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.

const server = new ApolloServer({
  typeDefs, // shorthand for `typeDefs: typeDefs`
});
Enter fullscreen mode Exit fullscreen mode

Learn more:

4. Start the server

Finally, we add the command to start our server.

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

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/
Enter fullscreen mode Exit fullscreen mode

While our server is running, we can access the 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

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

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

Learn more:

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!

Oldest comments (0)