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:
- Apollo Server CodeSandbox template — 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
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
andnpm
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 thescripts
- 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 inpackage.json
.- If using a template or adding to an existing app, open your
package.json
and see what the main script is called.
- If using a template or adding to an existing app, open your
We are ready to set up the GraphQL server!
Steps
- Install dependencies and import functions
- Create our type definitions schema
- Create a new ApolloServer object
- 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
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");
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
`;
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]
}
`;
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.
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.
const server = new ApolloServer({
typeDefs, // shorthand for `typeDefs: typeDefs`
});
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}`);
});
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 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
.
Once we have our query for nothings
, press the "Run" icon, and our server returns the data (or lack thereof, in this case).
That's it, we've got a server that serves nothing! 😁 Below is the full server code.
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!
Top comments (0)