Migrating to v2.0
How to migrate to Apollo Server 2.0
Apollo Server 2.0 dramatically simplifies the API for building a GraphQL server without compromising on features. It's also completely backward compatible, so you don't have to worry about breaking changes when upgrading.
While it's possible to migrate an existing server to 2.0 without any changes, we recommend changing to new patterns we're suggesting in order to take advantage of all the latest Apollo Server features, reduce the boilerplate, and enable future flexibility. To learn how to migrate to 2.0 from version 1.0, please read the following guide.
The gql
tag
Apollo Server 2.0 ships with the gql
tag for editor syntax highlighting and auto-formatting with Prettier. In the future, we will be using it for statically analyzing GraphQL queries, so Apollo Server requires wrapping your schema with gql
.
The gql
tag parses the query string into an AST and is now exported from the new apollo-server
package.
1const { ApolloServer, gql } = require('apollo-server');
2
3const typeDefs = gql`
4 type Query {
5 hello: String
6 }
7`;
8
9//Some projects use schemas imported from external files
10const fs = require('fs');
11const typeDefs = gql`${fs.readFileSync(__dirname.concat('/schema.graphql'), 'utf8')}`;
12
13//gql can also be used as regular function to convert a string to an AST
14const typeDefs = gql(fs.readFileSync(__dirname.concat('/schema.graphql'), 'utf8'))
Changes to app dependencies
Apollo Server 2.0 requires Node.js v6 and higher.
Apollo Server 2.0 simplifies implementing a GraphQL server. Apollo Server 1.0 revolved around providing middleware-based solutions, which had to be added to an application which already existed. These middleware implementations were tied to the HTTP server in use (e.g. apollo-server-express
for Express implementations, apollo-server-hapi
for hapi, etc.).
There is a consideration to be made when following the rest of the guide:
Middleware option: If the application being migrated implements Apollo Server alongside other middleware, there are some packages which can be removed, but adding the
apollo-server-{integration}
package and switching to using the newapplyMiddleware
API should still simplify the setup. In this case, check the Middleware section.Stand-alone option: If the application being migrated is only used as a GraphQL server, Apollo Server 2.0 eliminates the need to run a separate HTTP server and allows some dependencies to be removed. In these cases, the Stand-alone option will reduce the amount of code necessary for running a GraphQL server.
Simplified usage
Check out the following changes for Apollo Server 2.0.
You no longer need to import
body-parser
to set upapollo-server-express
.You no longer need to import
makeExecutableSchema
fromgraphql-tools
.You no longer need to import
graphqlExpress
andgraphiqlExpress
fromapollo-server-express
.You should pass in
typeDefs
andresolvers
as parameters to an instance of Apollo Server.If the server is only functioning as a GraphQL server, it's no longer necessary to run your own HTTP server (like
express
).
Middleware
With the middleware option used by Apollo Server 1.0 users, it is necessary to install the 2.0 version of apollo-server-express
. To do this, install via the terminal:
1npm install apollo-server-express graphql
The changes are best shown by comparing the before and after of the application.
Apollo Server 1 (old pattern)
An example of using Apollo Server 1 with the Express framework:
1const express = require('express');
2const bodyParser = require('body-parser');
3const { makeExecutableSchema } = require('graphql-tools');
4const { graphqlExpress } = require('apollo-server-express');
5
6const typeDefs = `
7 type Query {
8 hello: String
9 }
10`;
11
12const resolvers = {
13 Query: {
14 hello: () => 'Hello world!'
15 },
16}
17
18const myGraphQLSchema = makeExecutableSchema({
19 typeDefs,
20 resolvers,
21});
22
23const PORT = 3000;
24
25const app = express();
26
27// bodyParser is needed just for POST.
28app.use('/graphql', bodyParser.json(), graphqlExpress({ schema: myGraphQLSchema }));
29
30app.listen(PORT);
Apollo Server 2 (new pattern)
Now, you can just do this instead:
1const express = require('express');
2const { ApolloServer, gql } = require('apollo-server-express');
3
4const PORT = 4000;
5
6const app = express();
7
8const typeDefs = gql`
9 type Query {
10 hello: String
11 }
12`;
13
14const resolvers = {
15 Query: {
16 hello: () => 'Hello world!'
17 },
18};
19
20const server = new ApolloServer({ typeDefs, resolvers });
21server.applyMiddleware({ app });
22
23app.listen({ port: PORT }, () =>
24 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
25)
Stand-alone
For starting a production-ready GraphQL server quickly, Apollo Server 2.0 ships with a built-in server, so starting a server (e.g. Express, Koa, etc.) is no longer necessary.
For these cases, it's possible to remove the existing apollo-server-{integrations}
package and add the new version 2.0 of apollo-server
. If using Express, this can be done by running:
1npm uninstall --save apollo-server-express
2
3npm install apollo-server graphql
An implementation with this pattern would look like:
1const { ApolloServer, gql } = require('apollo-server');
2
3// Construct a schema, using GraphQL schema language
4const typeDefs = gql`
5 type Query {
6 announcement: String
7 }
8`;
9
10// Provide resolver functions for your schema fields
11const resolvers = {
12 Query: {
13 announcement: () =>
14 `Say hello to the new Apollo Server! A production ready GraphQL server with an incredible getting started experience.`
15 }
16};
17
18const server = new ApolloServer({ typeDefs, resolvers });
19
20server.listen().then(({ url }) => {
21 console.log(`🚀 Server ready at ${url}`);
22});
Adding Additional Middleware to Apollo Server 2
For middleware that is collocated with the GraphQL endpoint, Apollo Server 2 allows middleware mounted on the same path before applyMiddleware
is called. For example, this server runs an authentication middleware before GraphQL execution.
1const express = require('express');
2const { ApolloServer, gql } = require('apollo-server-express');
3
4const app = express();
5const path = '/graphql';
6
7const server = new ApolloServer({ typeDefs, resolvers });
8
9//Mount a jwt or other authentication middleware that is run before the GraphQL execution
10app.use(path, jwtCheck);
11
12server.applyMiddleware({ app, path });
13
14app.listen({ port: 4000 }, () =>
15 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
16)
Using an Existing Schema
For many existing instances of Apollo Server, the schema is created at runtime before server startup, using makeExecutableSchema
or mergeSchemas
. Apollo Server 2 stays backwards compatible with these more complex schemas, accepting it as the schema
field in the server constructor options. Additionally, Apollo Server 2 exports all of graphql-tools
, so makeExecutableSchema
and other functions can be imported directly from Apollo Server.
1const {
2 ApolloServer,
3 makeExecutableSchema
4} = require('apollo-server');
5
6// The `typeDefs` passed into `makeExecutableSchema` are _intentionally_
7// passed in without using the `gql` tag since it requires a `String` and
8// the `gql` tag returns an AST. When not using `makeExecutableSchema`
9// and passing `typeDefs` into the `ApolloServer` constructor, it's
10// recommended to use the `gql` tag.
11const typeDefs = `
12 type Query {
13 hello: String
14 }
15`;
16
17const schema = makeExecutableSchema({
18 typeDefs,
19 resolvers,
20});
21//mergeSchemas can be imported from apollo-server
22//const schema = mergeSchemas(...);
23
24const server = new ApolloServer({ schema });
25
26server.listen().then(({ url }) => {
27 console.log(`🚀 Server ready at ${url}`);
28});
Constructing an Executable Schema Manually
While we recommend the use schema-definition language (SDL) for defining a GraphQL schema since we feel it's more human-readable and language-agnostic, Apollo Server 2 also supports schemas which are built with the graphql-js
's graphql/type
notation by passing a GraphQLSchema
to the schema
option of the ApolloServer
constructor.
For example, using this technique the above schema might be represented and used as:
1const {
2 graphql,
3 GraphQLSchema,
4 GraphQLObjectType,
5 GraphQLString
6} = require('graphql');
7const { ApolloServer } = require('apollo-server');
8
9const schema = new GraphQLSchema({
10 query: new GraphQLObjectType({
11 name: 'RootQueryType',
12 fields: {
13 hello: {
14 type: GraphQLString,
15 resolve() {
16 return 'hello world';
17 }
18 }
19 }
20 })
21});
22
23const server = new ApolloServer({ schema });
24
25server.listen().then(({ url }) => {
26 console.log(`🚀 Server ready at ${url}`);
27});
Accessing Request Headers
Apollo Server 1 allowed request headers to be used in the construction of the GraphQL options. Apollo Server 2 allows constructor to create the context based upon the request.
1//old way
2graphqlExpress((req, res) => ({
3 schema: myGraphQLSchema,
4 context: {
5 token: req.headers['auth-token'],
6 },
7}))
8
9//new way
10new ApolloServer({
11 schema: myGraphQLSchema,
12 context: ({req, res}) => ({
13 token: req.headers['auth-token'],
14 }),
15});
Replacing logFunction
Apollo Server 2 removes the logFunction
to reduce the exposure of internal implementation details. The experimental, non-public graphql-extensions
provides a more structured and flexible way of instrumenting Apollo Server. An explanation of to do more granular logging, can be found in the metrics section.
Replacing GraphiQL
Apollo Server 2 ships with GraphQL Playground instead of GraphiQL and collocates the GUI with the endpoint. GraphQL playground can be customized in the following manner.
1const { ApolloServer, gql } = require('apollo-server-express');
2
3const server = new ApolloServer({
4 // These will be defined for both new or existing servers
5 typeDefs,
6 resolvers,
7 playground: {
8 endpoint?: string
9 subscriptionEndpoint?: string
10 tabs: [
11 {
12 endpoint: string
13 query: string
14 variables?: string
15 responses?: string[]
16 headers?: { [key: string]: string }
17 },
18 ],
19 },
20});
21
22server.applyMiddleware({
23 app, // app is from an existing express app
24});
25
26app.listen({ port: 4000 }, () =>
27 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
28)
Some Apollo Server 1 implementations use a custom version of GraphiQL, which can be added to Apollo Server 2 as a middleware or ported to use the React version of GraphQL Playground.