API Reference: startStandaloneServer
This API reference documents the startStandaloneServer
function.
Overview
This startStandaloneServer
function helps you get started with Apollo Server quickly. This function is recommended for all projects that don't require serverless support or a particular Node.js framework (such as Fastify). Under the hood, the startStandaloneServer
function uses Apollo Server 4's Express integration (i.e., expressMiddleware
).
Because it sets helpful defaults, this function is less configurable than other Apollo Server integrations. Complex projects might eventually need to swap to using expressMiddleware
(this process is straightforward).
startStandaloneServer
In the examples below, we use top-level
await
calls to start our server asynchronously. Check out our Getting Started guide to see how we configured our project to support this.
The startStandaloneServer
function accepts two arguments. The first required argument is the instance of ApolloServer
to begin listening for incoming requests:
1import { ApolloServer } from '@apollo/server';
2import { startStandaloneServer } from '@apollo/server/standalone';
3
4const server = new ApolloServer({ typeDefs, resolvers });
5
6// `startStandaloneServer` returns a `Promise` with the
7// the URL that the server is listening on.
8const { url } = await startStandaloneServer(server);
The startStandaloneServer
function's second optional argument is an object for configuring your server's options, which can contain the following properties:
Options
Name / Type |
Description |
---|---|
| An optional asynchronous context initialization function.The context function should return an object that all your server's resolvers share during an operation's execution. This enables resolvers to share helpful context values, such as a database connection.The context function receives req and res options which are http.IncomingMessage and http.ServerResponse types. |
| An optional listen configuration object. The listen option accepts an object with the same properties as the net.Server.listen options object.If no port is specified, this defaults to using {port: 4000} . |
Example
Below is a full example of setting up startStandaloneServer
:
1// npm install @apollo/server graphql
2import { ApolloServer } from '@apollo/server';
3import { startStandaloneServer } from '@apollo/server/standalone';
4import { typeDefs, resolvers } from './schema';
5
6interface MyContext {
7 token?: String;
8}
9
10
11const server = new ApolloServer<MyContext>({ typeDefs, resolvers });
12const { url } = await startStandaloneServer(server, {
13 context: async ({ req }) => ({ token: req.headers.token }),
14 listen: { port: 4000 },
15});
16console.log(`🚀 Server ready at ${url}`);
Swapping to expressMiddleware
The startStandaloneServer
function is not right for every use case, particularly if you need to customize your server's behavior. For example, you might want to customize your CORS behavior, run some middleware before processing GraphQL requests, or serve other endpoints from the same server.
In these cases, we recommend you swap out startStandaloneServer
for expressMiddleware
(unless you are confident that you want to use a different Node.js framework). This change requires only a few lines and has a minimal effect on your server's existing behavior (startStandaloneServer
uses expressMiddleware
under the hood).
We recommend Express because it's the most popular Node.js web framework, and it integrates well with many other popular libraries. It does have its limitations (for example, Express async support is not built around
Promise
s andasync
functions), but backward incompatible changes to the framework are rarer than in newer libraries.
Example
Let's say our current startStandaloneServer
setup uses the following code:
1import { ApolloServer } from '@apollo/server';
2import { startStandaloneServer } from '@apollo/server/standalone';
3import { typeDefs, resolvers } from './schema';
4
5interface MyContext {
6 token?: String;
7}
8
9const server = new ApolloServer<MyContext>({ typeDefs, resolvers });
10const { url } = await startStandaloneServer(server, {
11 context: async ({ req }) => ({ token: req.headers.token }),
12 listen: { port: 4000 },
13});
14console.log(`🚀 Server ready at ${url}`);
To swap to using expressMiddleware
, you'll first need to install the following packages so you'll be able to set up CORS for your server:
1npm install express cors
Next, we can modify our code to match the following:
1// npm install @apollo/server express graphql cors
2import { ApolloServer } from '@apollo/server';
3import { expressMiddleware } from '@apollo/server/express4';
4import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
5import express from 'express';
6import http from 'http';
7import cors from 'cors';
8import { typeDefs, resolvers } from './schema';
9
10interface MyContext {
11 token?: String;
12}
13
14// Required logic for integrating with Express
15const app = express();
16// Our httpServer handles incoming requests to our Express app.
17// Below, we tell Apollo Server to "drain" this httpServer,
18// enabling our servers to shut down gracefully.
19const httpServer = http.createServer(app);
20
21// Same ApolloServer initialization as before, plus the drain plugin
22// for our httpServer.
23const server = new ApolloServer<MyContext>({
24 typeDefs,
25 resolvers,
26 plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
27});
28// Ensure we wait for our server to start
29await server.start();
30
31// Set up our Express middleware to handle CORS, body parsing,
32// and our expressMiddleware function.
33app.use('/',
34 cors<cors.CorsRequest>(),
35 // 50mb is the limit that `startStandaloneServer` uses, but you may configure this to suit your needs
36 express.json({ limit: '50mb' }),
37 // expressMiddleware accepts the same arguments:
38 // an Apollo Server instance and optional configuration options
39 expressMiddleware(server, {
40 context: async ({ req }) => ({ token: req.headers.token }),
41 }),
42);
43
44// Modified server startup
45await new Promise<void>(resolve => httpServer.listen({ port: 4000 }, resolve));
46console.log(`🚀 Server ready at http://localhost:4000/`);