DEV Community

Cover image for ⚡ Add a GraphQL Server to a RESTful Express.js API in 2 Minutes
Khalil Stemmler for Apollo GraphQL

Posted on

15 7

⚡ Add a GraphQL Server to a RESTful Express.js API in 2 Minutes

⚡ Add a GraphQL Server to a RESTful Express.js API in 2 Minutes

You can get a lot done in 2 minutes, like microwaving popcorn, sending a text message, eating a cupcake, and hooking up a GraphQL server.

Yup. If you have an old Express.js RESTful API lying around or you're interested in incrementally adopting GraphQL, we only need 2 minutes to hook it up with a fresh new GraphQL Server.

Ready? Set. Go!

Let's say that your server looked something like the following.

import express from 'express';
import { apiRouter } from './router';

const app = express();
const port = process.env.PORT || 5000;

// Existing routes for our Express.js app
app.use('/api/v1', apiRouter);

app.listen(port, () => console.log(`[App]: Listening on port ${port}`))
Enter fullscreen mode Exit fullscreen mode

At the root of your project, npm install apollo-server-express as a dependency.

npm install apollo-server-express --save
Enter fullscreen mode Exit fullscreen mode

Go to where your Express app is defined and import ApolloServer and gql from apollo-server-express.

import { ApolloServer, gql } from 'apollo-server-express'
Enter fullscreen mode Exit fullscreen mode

Next, create an instance of an ApolloServer with the simplest possible GraphQL type definitions and resolvers.

const server = new ApolloServer({
  typeDefs: gql`
    type Query {
      hello: String
    }
  `,
  resolvers: {
    Query: {
      hello: () => 'Hello world!',
    },
  }
})
Enter fullscreen mode Exit fullscreen mode

Lastly, use ApolloServer's applyMiddleware method to pass in our Express.js server.

server.applyMiddleware({ app })
Enter fullscreen mode Exit fullscreen mode

Boom. That's it!

Your code should look something like this.

import express from 'express';
import { v1Router } from './api/v1';
import { ApolloServer, gql } from 'apollo-server-express'

const app = express();
const port = process.env.PORT || 5000;

const server = new ApolloServer({
  typeDefs: gql`
    type Query {
      hello: String
    }
  `,
  resolvers: {
    Query: {
      hello: () => 'Hello world!',
    },
  }
})

server.applyMiddleware({ app })

app.use('/api/v1', v1Router);

app.listen(port, () => {
  console.log(`[App]: Listening on port ${port}`)
})
Enter fullscreen mode Exit fullscreen mode

If you navigate to localhost:5000/graphql, you should be able to see your GraphQL schema in the GraphQL playground.

Alt Text

Note: If you want to change the URL that the GraphQL endpoint sits at from /graphql to something else, you can pass in a path option to server.applyMiddleware() with the URL you want, like path: '/specialUrl'. Check out the docs for full API usage.

How simple was that? Is your popcorn finished? 😉

Summary

Here's what we did.

  1. Install apollo-server-express
  2. Create a new ApolloServer
  3. Connect your GraphQL Server with server.applyMiddleware

I personally really love the fact that Apollo Server is non-intrusive and can be tacked on any project as an alternative way to communicate between services and applications.

Where to go from here

If you're new to Apollo and GraphQL, a great way to learn is to actually build something in real life. For that reason, I highly recommend checking out the Apollo Fullstack Tutorial (you can also learn in TypeScript now 🔥).

I'm Khalil Stemmler, a Developer Advocate at Apollo GraphQL. I teach advanced TypeScript, GraphQL, and Node.js best practices for large-scale applications. Feel free to ping me on Twitter if you need help with anything Apollo, TypeScript, or architecture-related. Cheers 🤠

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (3)

Collapse
 
paul_melero profile image
Paul Melero

But what's in the ./router, my man?

Collapse
 
stemmlerjs profile image
Khalil Stemmler

Scary, secret things... Just kidding.

Usually, my router is where I delegate chunks of the API off to appropriate sub-routers to then get more detailed with how things get done :)

I also usually version my REST APIs (like v1Router).

import express from 'express'
import { userRouter } from '../../../../modules/users/infra/http/routes';
import { memberRouter, commentRouter } from '../../../../modules/forum/infra/http/routes';
import { postRouter } from '../../../../modules/forum/infra/http/routes/post';

const v1Router = express.Router();

v1Router.get('/', (req, res) => {
  return res.json({ message: "Yo! we're up" });
})

v1Router.use('/users', userRouter);
v1Router.use('/members', memberRouter);
v1Router.use('/posts', postRouter);
v1Router.use('/comments', commentRouter);

export { v1Router } // or { router }, like the rest of the code.
Enter fullscreen mode Exit fullscreen mode

You can see this code in the project it's from here, btw.

Collapse
 
paul_melero profile image
Paul Melero

Appreciated ❤️

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series