Cover photo by Two Paddles Axe and Leatherwork on Unsplash
Scenario: You have your first schema running on your Apollo server but a new GraphQL API shows up and you need to work with it in your client right away without too much orquestation.
This tutorial will try to get you from point A to point B as fast as possible. We will make a small API to solve our problem and for future reuse. You can use it right away but we will be explaining each piece step by step to get the inner workings.
A note:
Stitching local with remote schemas, I think, works perfectly in the situation where you are starting to stitch. Why? Because you have your first schema already up and running. If a GraphQL service shows up just append this new remote schema on top to start consuming it.
I'm telling you this because there is another way of working this out AFAIK but we would need to start another microservice to serve as a proxy to both of our APIs (local and remote schemas will be both remote now). I think this could work well when you have too many services but for a start let's just use our current server and enhance it with a new remote schema on top of it. It's faster, it's one less service to run, it works.
Right now supposedly we have this setup for our server.
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`π Server ready at ${url}`);
});
We are going to replace previous code with this module.
const { ApolloServer, makeExecutableSchema } = require('apollo-server')
const { HttpLink } = require('apollo-link-http')
const {
introspectSchema,
makeRemoteExecutableSchema,
mergeSchemas,
} = require('graphql-tools')
const fetch = require('node-fetch')
async function startServer({
localSchema: { resolvers, typeDefs },
remoteSchema: { uri },
}) {
const remoteHttpLink = new HttpLink({
uri,
fetch,
})
const remoteSchemaInstrospection = await introspectSchema(remoteHttpLink)
const remoteSchemaExecutable = makeRemoteExecutableSchema({
schema: remoteSchemaInstrospection,
link: remoteHttpLink,
})
const localSchema = makeExecutableSchema({
typeDefs,
resolvers,
})
const mergedSchemas = mergeSchemas({
schemas: [localSchema, remoteSchemaExecutable],
})
const server = new ApolloServer({ schema: mergedSchemas })
return await server.listen()
}
module.exports = startServer
First we are going to make a request to our external GraphQL API. We pass to the config object our uri
and a reference to the fetch
library.
const remoteHttpLink = new HttpLink({
uri,
fetch,
})
We use the instrospectionSchema
function to retrive the schema from our remote GraphQL service. Only argument is our previously defined HttpLink
instance.
const remoteSchemaInstrospection = await introspectSchema(remoteHttpLink)
We got our schema after introspection but now we are still missing making it executable. So it's a two step process. Being executable will enables us to later on merge it with our local one.
const remoteSchemaExecutable = makeRemoteExecutableSchema({
schema: remoteSchemaInstrospection,
link: remoteHttpLink,
})
Next we create our local schema using makeExecutableSchema
passing a config object as argument with our typeDefs
and resolvers
just like the typical server config object we saw at the beginning.
const localSchema = makeExecutableSchema({
typeDefs,
resolvers,
})
Merge both schemas with mergeSchemas
const mergedSchemas = mergeSchemas({
schemas: [localSchema, remoteSchemaExecutable],
})
Pass it to our server in its config object and start it invoking listen
as usual.
const server = new ApolloServer({ schema: mergedSchemas })
return await server.listen()
We are done with the module breakdown π. Now let's use it!
startServer
has as argument one config object that has two properties:
-
localSchema
Object with two keys.resolvers
andtypeDefs
. -
remoteSchema
Object with one key.uri
: string of our external GraphQL API.
startServer({
localSchema: {
resolvers,
typeDefs,
},
remoteSchema: {
uri: 'https://01uhb.sse.codesandbox.io/',
},
}).then(({ url }) => {
console.log(`π => Server ready at ${url}`)
})
And that's it. Now our current server has both of our schemas available.
Play with it yourself. Here's a codesandbox with the GraphQL server and our module in action. We have two queries. hello
is local and the goodbye
query is being merge.
You can grab the external Graphql service here: https://codesandbox.io/s/apollo-server-01uhb
This is just the beginning. You have a lot to tweak and learn about stitching from here.
What if some types repeat between schemas?
What if I need to use the result type of one query in another one as an argument?
New challenges bring new ways to extend and work with combined schemas.
Hope this tut is a good first step into your stitching journey!
Top comments (0)