I am trying to integrate ApolloClient with Gatsby V2, but I am having some troubles since it already includes GraphQL and they use different versions.
Looking on the internet, I have found a workaround in develop environment using Yarn with:
"resolutions": {
"graphql": "0.13.2"
},
Unfortunately, it won't compile with gatsby build
and outputs the following:
error Building static HTML for pages failed
See our docs page on debugging HTML builds for help https://gatsby.app/debug-html
38 | var args = [a, b, c, d, e, f];
39 | var argIndex = 0;
> 40 | error = new Error(
| ^
41 | format.replace(/%s/g, function() { return args[argIndex++]; })
42 | );
43 | error.name = 'Invariant Violation';
WebpackError: Invariant Violation: Could not find "client" in the context of ApolloConsumer. Wrap the root component in an <ApolloProvider>
- invariant.js:40 invariant
[lib]/[invariant]/invariant.js:40:1
- ApolloConsumer.js:4 ApolloConsumer
[lib]/[react-apollo]/ApolloConsumer.js:4:1
- bootstrap:25 a.render
lib/webpack/bootstrap:25:1
- bootstrap:24 a.read
lib/webpack/bootstrap:24:1
- bootstrap:36 renderToString
lib/webpack/bootstrap:36:1
- static-entry.js:190 Module../.cache/static-entry.js.__webpack_exports__.default.React.Component [as default]
lib/.cache/static-entry.js:190:18
- bootstrap:24 Promise
lib/webpack/bootstrap:24:1
- api-ssr-docs.js:135 Promise._execute
lib/.cache/api-ssr-docs.js:135:1
- bootstrap:68 new Promise
lib/webpack/bootstrap:68:1
- bootstrap:5 tryCatcher
lib/webpack/bootstrap:5:1
- bootstrap:50 MappingPromiseArray._promiseFulfilled
lib/webpack/bootstrap:50:1
- api-runner-ssr.js:6 MappingPromiseArray.PromiseArray._iterate
This is the way I wrap my ApolloProvider
:
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it
import React from 'react'
import { CookiesProvider } from 'react-cookie'
import { ApolloProvider } from 'react-apollo'
import ApolloClient from 'apollo-boost'
import Cookies from 'universal-cookie'
import { version } from './src/graphql'
const cookies = new Cookies()
const client = new ApolloClient({
uri: process.env.GRAPHQL_URL,
request: operation => {
operation.setContext({
headers: {
Authorization: cookies.get('jwt')
? `Bearer ${cookies.get('jwt')}`
: undefined,
},
})
},
})
export const wrapRootElement = ({ element }) => {
return (
<CookiesProvider>
<ApolloProvider client={client}>{element}</ApolloProvider>
</CookiesProvider>
)
}
System:
OS: macOS 10.14.2
CPU: (8) x64 Intel(R) Core(TM) i7-6920HQ CPU @ 2.90GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.15.0 - ~/.nvm/versions/node/v8.15.0/bin/node
Yarn: 1.3.2 - /usr/local/bin/yarn
npm: 6.4.1 - ~/.nvm/versions/node/v8.15.0/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 71.0.3578.98
Firefox: 57.0.4
Safari: 12.0.2
npmPackages:
gatsby: ^2.0.76 => 2.0.91
gatsby-image: ^2.0.20 => 2.0.26
gatsby-plugin-manifest: ^2.0.9 => 2.0.13
gatsby-plugin-offline: ^2.0.16 => 2.0.21
gatsby-plugin-react-helmet: ^3.0.2 => 3.0.5
gatsby-plugin-sass: ^2.0.7 => 2.0.7
gatsby-plugin-sharp: ^2.0.14 => 2.0.17
gatsby-source-filesystem: ^2.0.8 => 2.0.16
gatsby-transformer-sharp: ^2.1.8 => 2.1.10
gatsby-config.js
:
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
'gatsby-plugin-sass',
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.app/offline
// 'gatsby-plugin-offline',
],
}
package.json
:
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <[email protected]>",
"engines": {
"node": "8.15.0"
},
"dependencies": {
"apollo-boost": "^0.1.25",
"dotenv": "^6.2.0",
"formik": "^1.4.2",
"gatsby": "^2.0.76",
"gatsby-image": "^2.0.20",
"gatsby-plugin-manifest": "^2.0.9",
"gatsby-plugin-offline": "^2.0.16",
"gatsby-plugin-react-helmet": "^3.0.2",
"gatsby-plugin-sass": "^2.0.7",
"gatsby-plugin-sharp": "^2.0.14",
"gatsby-source-filesystem": "^2.0.8",
"gatsby-transformer-sharp": "^2.1.8",
"graphql": "^0.13.2",
"graphql-tag": "^2.10.1",
"node-sass": "^4.11.0",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-apollo": "^2.3.3",
"react-cookie": "^3.0.8",
"react-dom": "^16.6.3",
"react-helmet": "^5.2.0",
"yup": "^0.26.7"
},
"keywords": [
"gatsby"
],
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"start": "gatsby serve --port ${PORT}",
"format": "prettier --write \"src/**/*.js\"",
"test": "echo \"Write tests! -> https://gatsby.app/unit-testing\"",
"heroku-postbuild": "gatsby build"
},
"devDependencies": {
"husky": "^1.3.1",
"prettier": "^1.15.2",
"pretty-quick": "^1.10.0"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
},
"resolutions": {
"graphql": "0.13.2"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
}
}
gatsby-node.js
:
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/node-apis/
*/
// You can delete this file if you're not using it
// Implement the Gatsby API “onCreatePage”. This is
// called after every page is created.
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
})
exports.onCreatePage = ({ page, actions }) => {
const { createPage } = actions
// Make the front page match everything client side.
// Normally your paths should be a bit more judicious.
if (page.path === `/`) {
page.matchPath = `/*`
createPage(page)
}
}
gatsby-browser.js
:
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it
import React from 'react'
import { CookiesProvider } from 'react-cookie'
import { ApolloProvider } from 'react-apollo'
import ApolloClient from 'apollo-boost'
import Cookies from 'universal-cookie'
import { version } from './src/graphql'
const cookies = new Cookies()
const client = new ApolloClient({
uri: process.env.GRAPHQL_URL,
request: operation => {
operation.setContext({
headers: {
Authorization: cookies.get('jwt')
? `Bearer ${cookies.get('jwt')}`
: undefined,
},
})
},
})
export const wrapRootElement = ({ element }) => {
return (
<CookiesProvider>
<ApolloProvider client={client}>{element}</ApolloProvider>
</CookiesProvider>
)
}
gatsby-ssr.js
: N/A
@guidolodetti Could you please link to a minimal reproduction repository for this?
@sidharthachatterjee here is the started project with my additional commit for ApolloClient. Using withApollo()
breaks the yarn build
task!
@devnasim you got same issue right ?
@guidolodetti @sidharthachatterjee look into that https://github.com/devnasim/gatsby-apollo-graphql
might be helpful.
Hey @guidolodetti
This is breaking because on SSR the root element is unwrapped and therefore Apollo Client complains about the lack of a Provider.
You'll want to implement wrapRootElement
in gatsby-ssr.js
as well like this:
import React from 'react'
import { ApolloProvider } from 'react-apollo'
import ApolloClient from 'apollo-boost'
const client = new ApolloClient({
uri: 'http://localhost:4000',
})
export const wrapRootElement = ({ element }) => (
<ApolloProvider client={client}>{element}</ApolloProvider>
)
Also you'll need to add isomorphic-fetch
to your dependencies since apollo looks for fetch to make HTTP requests
You can check out a minimal working example of Gatsby with Apollo at https://github.com/jlengstorf/gatsby-with-apollo (H/T @jlengstorf)
Hi! 👋
I built an app live at the GraphQL Summit that does this. Video is here: https://www.youtube.com/watch?v=wNUg1jpj9T0&index=9&t=168s&list=PLz8Iz-Fnk_eQGt4-VFFCXYuYcuKaw4F07
I’m going to close this, but please follow up if you have any additional questions!
Hi @jlengstorf, your sample codes link does not use any plugin to bring in apollo client. there is a plugin gatsby theme apollo which can be used to enable client side apollo too. Any difference between using your method vs the plugin? Thanks
@myhendry to give you some context. The example code in the repo you mentioned is meant to show you that you're not bound to the Gatsby graphql layer exclusively, you can use apollo just fine without any issues. More even if you should need more than just fetching the data, more specificaly if you need to do some mutations or probably subscriptions. Technically there aren't any differences, the theme that currently exists it's basically a pre built kit that will streamline your development process, so that you don't waste time on adding the packages and creating the files and adding the code, leaving you with just some minor configurations that are probably required and focus on getting content into the you're developing
Thanks @jonniebigodes for the explanation. Got it :)
hey i followed the process of adding apollo clien by referencing https://github.com/jlengstorf/gatsby-with-apollo (H/T @jlengstorf)
but still i can't see the content on view source for SSR
Most helpful comment
Hi! 👋
I built an app live at the GraphQL Summit that does this. Video is here: https://www.youtube.com/watch?v=wNUg1jpj9T0&index=9&t=168s&list=PLz8Iz-Fnk_eQGt4-VFFCXYuYcuKaw4F07
I’m going to close this, but please follow up if you have any additional questions!