diff --git a/docker-compose.yml b/docker-compose.yml
index 808f631..e086e7a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,10 +5,10 @@ services:
restart: always
build: .
ports:
- - '3000:3000'
- # webserver:
- # container_name: webserver
- # restart: unless-stopped
- # build: nginx
- # ports:
- # - '80:80'
\ No newline at end of file
+ - '3000'
+ webserver:
+ container_name: webserver
+ restart: unless-stopped
+ build: nginx
+ ports:
+ - '80:80'
\ No newline at end of file
diff --git a/graphql/index.js b/graphql/index.js
new file mode 100644
index 0000000..5b24eb2
--- /dev/null
+++ b/graphql/index.js
@@ -0,0 +1,8 @@
+import { makeExecutableSchema } from 'graphql-tools'
+import { typeDefs } from './typeDefs'
+import { resolvers } from './resolvers'
+
+export const schema = makeExecutableSchema({
+ typeDefs,
+ resolvers
+})
diff --git a/lib/apollo.js b/lib/apollo.js
index e72d87b..b8b95b9 100644
--- a/lib/apollo.js
+++ b/lib/apollo.js
@@ -1,13 +1,148 @@
-import { withData } from 'next-apollo'
-import { HttpLink } from 'apollo-boost'
+import React from 'react'
+import Head from 'next/head'
+import { ApolloProvider } from '@apollo/react-hooks'
+import { ApolloClient } from 'apollo-client'
+import { InMemoryCache } from 'apollo-cache-inmemory'
-const config = {
- link: new HttpLink({
- uri: process.env.GRAPHQL_API_URI,
- opts: {
- credentials: 'same-origin'
+let globalApolloClient = null
+
+/**
+ * Creates and provides the apolloContext
+ * to a next.js PageTree. Use it by wrapping
+ * your PageComponent via HOC pattern.
+ * @param {Function|Class} PageComponent
+ * @param {Object} [config]
+ * @param {Boolean} [config.ssr=true]
+ */
+export function withApollo (PageComponent, { ssr = true } = {}) {
+ const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
+ const client = apolloClient || initApolloClient(apolloState)
+ return (
+
+
+
+ )
+ }
+
+ // Set the correct displayName in development
+ if (process.env.NODE_ENV !== 'production') {
+ const displayName =
+ PageComponent.displayName || PageComponent.name || 'Component'
+
+ if (displayName === 'App') {
+ console.warn('This withApollo HOC only works with PageComponents.')
}
+
+ WithApollo.displayName = `withApollo(${displayName})`
+ }
+
+ if (ssr || PageComponent.getInitialProps) {
+ WithApollo.getInitialProps = async ctx => {
+ const { AppTree } = ctx
+
+ // Initialize ApolloClient, add it to the ctx object so
+ // we can use it in `PageComponent.getInitialProp`.
+ const apolloClient = (ctx.apolloClient = initApolloClient())
+
+ // Run wrapped getInitialProps methods
+ let pageProps = {}
+ if (PageComponent.getInitialProps) {
+ pageProps = await PageComponent.getInitialProps(ctx)
+ }
+
+ // Only on the server:
+ if (typeof window === 'undefined') {
+ // When redirecting, the response is finished.
+ // No point in continuing to render
+ if (ctx.res && ctx.res.finished) {
+ return pageProps
+ }
+
+ // Only if ssr is enabled
+ if (ssr) {
+ try {
+ // Run all GraphQL queries
+ const { getDataFromTree } = await import('@apollo/react-ssr')
+ await getDataFromTree(
+
+ )
+ } catch (error) {
+ // Prevent Apollo Client GraphQL errors from crashing SSR.
+ // Handle them in components via the data.error prop:
+ // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
+ console.error('Error while running `getDataFromTree`', error)
+ }
+
+ // getDataFromTree does not call componentWillUnmount
+ // head side effect therefore need to be cleared manually
+ Head.rewind()
+ }
+ }
+
+ // Extract query data from the Apollo store
+ const apolloState = apolloClient.cache.extract()
+
+ return {
+ ...pageProps,
+ apolloState
+ }
+ }
+ }
+
+ return WithApollo
+}
+
+/**
+ * Always creates a new apollo client on the server
+ * Creates or reuses apollo client in the browser.
+ * @param {Object} initialState
+ */
+function initApolloClient (initialState) {
+ // Make sure to create a new client for every server-side request so that data
+ // isn't shared between connections (which would be bad)
+ if (typeof window === 'undefined') {
+ return createApolloClient(initialState)
+ }
+
+ // Reuse client on the client-side
+ if (!globalApolloClient) {
+ globalApolloClient = createApolloClient(initialState)
+ }
+
+ return globalApolloClient
+}
+
+/**
+ * Creates and configures the ApolloClient
+ * @param {Object} [initialState={}]
+ */
+function createApolloClient (initialState = {}) {
+ const ssrMode = typeof window === 'undefined'
+ const cache = new InMemoryCache().restore(initialState)
+
+ // Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
+ return new ApolloClient({
+ ssrMode,
+ link: createIsomorphLink(),
+ cache
})
}
-export default withData(config)
+function createIsomorphLink () {
+ if (typeof window === 'undefined') {
+ const { SchemaLink } = require('apollo-link-schema')
+ const { schema } = require('../graphql')
+ return new SchemaLink({ schema })
+ } else {
+ const { HttpLink } = require('apollo-link-http')
+ return new HttpLink({
+ uri: '/api/graphql',
+ credentials: 'same-origin'
+ })
+ }
+}
diff --git a/next.config.js b/next.config.js
index 5a3fc12..d6ef8db 100644
--- a/next.config.js
+++ b/next.config.js
@@ -9,8 +9,5 @@ module.exports = withSass({
config.optimization.minimizer.push(new OptimizeCSSAssetsPlugin({}))
return config
- },
- env: {
- GRAPHQL_API_URI: 'http://localhost:3000/api/graphql'
}
})
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
index 8dc07a4..e65ef81 100644
--- a/nginx/Dockerfile
+++ b/nginx/Dockerfile
@@ -2,4 +2,4 @@ FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
-COPY default.conf /etc/nginx/conf.d/
\ No newline at end of file
+COPY default.conf /etc/nginx/conf.d/
diff --git a/package-lock.json b/package-lock.json
index aed6789..62c7468 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1911,6 +1911,15 @@
"tslib": "^1.9.3"
}
},
+ "apollo-link-schema": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/apollo-link-schema/-/apollo-link-schema-1.2.4.tgz",
+ "integrity": "sha512-tLpqd2PSddXJDqA25aERh1U6SsZZBX1isPXSa8FbxvU4Dd8n/DmCOE4mqHyFasgjqLN1zFWL7jgf964LPrAp7A==",
+ "requires": {
+ "apollo-link": "^1.2.13",
+ "tslib": "^1.9.3"
+ }
+ },
"apollo-server-caching": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.1.tgz",
@@ -6932,15 +6941,6 @@
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
- "isomorphic-unfetch": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.0.0.tgz",
- "integrity": "sha512-V0tmJSYfkKokZ5mgl0cmfQMTb7MLHsBMngTkbLY0eXvKqiVRRoZP04Ly+KhKrJfKtzC9E6Pp15Jo+bwh7Vi2XQ==",
- "requires": {
- "node-fetch": "^2.2.0",
- "unfetch": "^4.0.0"
- }
- },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -8214,31 +8214,11 @@
}
}
},
- "next-apollo": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/next-apollo/-/next-apollo-3.1.10.tgz",
- "integrity": "sha512-VX64IW7h6Rdg+Ma0y8ryAIz7IfyLaz6Nd4VITuhfXFZ3nj51blcjRR6kc4E945SPk2WdrIMlLRZubgPRAgh9Ug==",
- "requires": {
- "@babel/runtime": "^7.4.5",
- "isomorphic-unfetch": "^3.0.0",
- "prop-types": "15.7.2",
- "prop-types-exact": "1.2.0",
- "url": "0.11.0"
- }
- },
"next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
},
- "next-with-apollo": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/next-with-apollo/-/next-with-apollo-5.0.0.tgz",
- "integrity": "sha512-JcMecKv6XtzsLf1hPKrbxM6g9sygnGdQugglmCDkfWhHZt1yziPa+g515qtw7in8A7Ed5W9PdaaaUn7CWWQ71w==",
- "requires": {
- "isomorphic-unfetch": "^3.0.0"
- }
- },
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
diff --git a/package.json b/package.json
index b0c915a..c694a20 100644
--- a/package.json
+++ b/package.json
@@ -12,12 +12,11 @@
"@apollo/react-ssr": "^3.1.3",
"@zeit/next-sass": "^1.0.1",
"apollo-boost": "^0.4.7",
+ "apollo-link-schema": "^1.2.4",
"apollo-server-micro": "^2.10.1",
"graphql-tag": "^2.10.3",
- "isomorphic-unfetch": "^3.0.0",
+ "graphql-tools": "^4.0.7",
"next": "9.2.2",
- "next-apollo": "^3.1.10",
- "next-with-apollo": "^5.0.0",
"node-sass": "^4.13.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"react": "16.13.0",
diff --git a/pages/api/graphql.js b/pages/api/graphql.js
index adf10a3..c1759bc 100644
--- a/pages/api/graphql.js
+++ b/pages/api/graphql.js
@@ -1,9 +1,7 @@
-const { ApolloServer, gql } = require('apollo-server-micro')
-const { typeDefs } = require('../../graphql/typeDefs')
-const { resolvers } = require('../../graphql/resolvers')
+import { ApolloServer } from 'apollo-server-micro'
+import { schema } from '../../graphql'
-const apolloServer = new ApolloServer({ typeDefs, resolvers })
-const handler = apolloServer.createHandler({ path: '/api/graphql' })
+const apolloServer = new ApolloServer({ schema })
export const config = { api: { bodyParser: false } }
-export default handler
+export default apolloServer.createHandler({ path: '/api/graphql' })
diff --git a/pages/articles.js b/pages/articles.js
index 31e70f9..5560b3d 100644
--- a/pages/articles.js
+++ b/pages/articles.js
@@ -2,7 +2,7 @@ import Layout from '../components/Layout/Layout'
import SEO from '../components/SEO/SEO'
import Query from '../components/Query/query'
import ARTICLES_QUERY from '../apollo/queries/articles/articles'
-import withData from '../lib/apollo'
+import { withApollo } from '../lib/apollo'
const Articles = () => {
return (
@@ -31,4 +31,4 @@ const Articles = () => {
)
}
-export default withData(Articles)
+export default withApollo(Articles)