Integrate Gatsby with Apito
Gatsby is the fast and flexible framework that makes building websites with any CMS, API, or database fun again.
The best Headless CMS for Gatsbyโ
Apito is a powerful headless cms to maintain and manage your Gatsby static site. it can deliver your content with GraphQL.
Gatsby automates code-splitting, image optimization, inlining critical styles, lazy-loading, and prefetching resources, and more to ensure your site is fast. You can read more about why you should use gatsby here
Apito with Gatsby benefitsโ
Being a static site generator brings a lot of advantages: Performance, security, lower cost of scaling but also an excellent developer experience.
Gatsby brings huge benefits to content creators and developers by helping to solve many of the challenges with the headless approach.
Apito provides a perfect solution as a source for Gatsbyโs static markup generation. Whether building a static site, or a more dynamic app/website Apito has you covered with its flexibility of content types, plugins, and customization.
Automate builds using Webhooksโ
You Take advantage of the built-in webhook feature that will allow you to automatically build your Gatsby project upon the update of your data.
Getting Started with Gatsbyโ
Follow the integration guide from our documentation to see how to consume Apito's Content API from Gatsby. As a Static Site Generator, Gatsby will fetch your content from Apito at build time. Therefore, you need to configure Gatsby to communicate with your Apito Project
First run this following command
Installโ
npm install gatsby-source-graphql
We recommend using dotenv, which will then expose environment variables. Read more about dotenv and using environment variables here. Then we can use these environment variables via process.env and configure our plugin.
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
// HTTP headers
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// HTTP headers alternatively accepts a function (allows async) | use the above or this one. Dont use both
headers: async () => {
return {
Authorization: await getAuthorizationToken(),
}
},
// Additional options to pass to node-fetch
fetchOptions: {},
},
},
How to Queryโ
{
# This is the fieldName you've defined in the config
features {
modules {
name
}
}
github {
viewer {
email
}
}
}
Schema definitionsโ
By default, the schema is introspected from the remote schema. The schema is cached in the .cache
directory, and refreshing the schema requires
deleting the cache (e.g. by restarting gatsby develop).
To control schema consumption, you can alternatively construct the schema definition by passing a createSchema callback. This way you could, for example, read schema SDL or introspection JSON. When the createSchema callback is used, the schema isnโt cached. createSchema can return a GraphQLSchema instance, or a Promise resolving to one.
You can use this method if your schema changes regularly.
const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")
module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
createSchema: async () => {
const json = JSON.parse(
fs.readFileSync(`${__dirname}/introspection.json`)
)
return buildClientSchema(json.data)
},
},
},
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
createSchema: async () => {
const sdl = fs.readFileSync(`${__dirname}/schema.sdl`).toString()
return buildSchema(sdl)
},
},
},
],
}
Composing Apollo Links for production network setupโ
Network requests can fail, return errors or take too long. Use Apollo Link to add retries, error handling, logging and more to your GraphQL requests.
Use the plugin's createLink
option to add a custom Apollo Link to your GraphQL requests.
You can compose different types of links, depending on the functionality you're trying to achieve. The most common links are:
@apollo/client/link/retry
for retrying queries that fail or time out@apollo/client/link/error
for error handling@apollo/client/link/http
for sending queries in http requests (used by default)
For more explanation of how Apollo Links work together, check out this Medium article: Productionizing Apollo Links.
Here's an example of using the HTTP link with retries (using @apollo/client/link/retry):
// gatsby-config.js
const { createHttpLink, from } = require(`@apollo/client`)
const { RetryLink } = require(`@apollo/client/link/retry`)
const retryLink = new RetryLink({
delay: {
initial: 100,
max: 2000,
jitter: true,
},
attempts: {
max: 5,
retryIf: (error, operation) =>
Boolean(error) && ![500, 400].includes(error.statusCode),
},
})
module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// `pluginOptions`: all plugin options
// (i.e. in this example object with keys `typeName`, `fieldName`, `url`, `createLink`)
createLink: pluginOptions =>
from([retryLink, createHttpLink({ uri: pluginOptions.url })]),
},
},
],
}
Refetching dataโ
By default, gatsby-source-graphql
will only refetch the data once the server is restarted. It's also possible to configure the plugin to periodically refetch the data.
The option is called refetchInterval
and specifies the timeout in seconds.
module.exports = {
plugins: [
// Simple config, passing URL
{
resolve: "gatsby-source-graphql",
options: {
// Arbitrary name for the remote schema Query type
typeName: "Apito",
// Field under which the remote schema will be accessible. You'll use this in your Gatsby query
fieldName: "apito",
// Url to query from
url: "https://api.apito.io/secured/graphql",
headers: {
// Learn about environment variables: https://gatsby.dev/env-vars
Authorization: `Bearer ${process.env.SECRET_TOKEN}`,
},
// refetch interval in seconds
refetchInterval: 60,
},
},
],
}
Performance tuningโ
By default, gatsby-source-graphql
executes each query in a separate network request.
But the plugin also supports query batching to improve query performance.
Caveat: Batching is only possible for queries starting at approximately the same time. In other words it is bounded by the number of parallel GraphQL queries executed by Gatsby (by default it is 4).
Fortunately, we can increase the number of queries executed in parallel by setting the environment variable
GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY
to a higher value and setting the batch
option of the plugin
to true
.
Example:
cross-env GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY=20 gatsby develop
With plugin config:
const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")
module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
batch: true,
},
},
],
}
By default, the plugin batches up to 5 queries. You can override this by passing
dataLoaderOptions
and set a maxBatchSize
:
const fs = require("fs")
const { buildSchema, buildClientSchema } = require("graphql")
module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "Apito",
fieldName: "apito",
url: "https://api.apito.io/secured/graphql",
batch: true,
// See https://github.com/graphql/dataloader#new-dataloaderbatchloadfn--options
// for a full list of DataLoader options
dataLoaderOptions: {
maxBatchSize: 10,
},
},
},
],
}
Having 20 parallel queries with 5 queries per batch means we are still running 4 batches in parallel.
Each project is unique so try tuning those two variables and see what works best for you. We've seen up to 5-10x speed-up for some setups.