Last active
October 30, 2018 04:01
-
-
Save renoirb/fad59b87f07f345d980994e1934410cf to your computer and use it in GitHub Desktop.
Attempt at making local module for Apollo GraphQL for Vue on Nuxt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f1cf052838fa56c305f57e02f039bea5d957d81f Mon Sep 17 00:00:00 2001 | |
From: Renoir Boulanger <hello@renoirboulanger.com> | |
Date: Mon, 29 Oct 2018 23:58:40 -0400 | |
Subject: [PATCH] Attempt adding own Vue Apollo | |
--- | |
modules/graphql.js | 73 ++++++++++++++++++++++++++++++++++ | |
nuxt.config.js | 1 + | |
package.json | 14 +++++-- | |
plugins/graphql-client.js | 41 +++++++++++++++++++ | |
utils/apollo-client-factory.js | 61 ++++++++++++++++++++++++++++ | |
5 files changed, 187 insertions(+), 3 deletions(-) | |
create mode 100644 modules/graphql.js | |
create mode 100644 plugins/graphql-client.js | |
create mode 100644 utils/apollo-client-factory.js | |
diff --git a/modules/graphql.js b/modules/graphql.js | |
new file mode 100644 | |
index 0000000..da1de9b | |
--- /dev/null | |
+++ b/modules/graphql.js | |
@@ -0,0 +1,73 @@ | |
+/** | |
+ * Nuxt.js GraphQL integration. | |
+ * | |
+ * Inspired by nuxt-community/apollo-module [1], but no need to de-duplicate Session. | |
+ * Refer to Nuxt module documentaiton [2] | |
+ * | |
+ * Methods available to this function are documented in api/internals-nuxt [3] as this.nuxt. | |
+ * | |
+ * [1]: https://github.com/nuxt-community/apollo-module/blob/master/lib/module.js | |
+ * [2]: https://nuxtjs.org/guide/modules | |
+ * [3]: https://nuxtjs.org/api/internals-nuxt | |
+ */ | |
+ | |
+/** | |
+ * path methods: | |
+ * - resolve | |
+ * - normalize | |
+ * - isAbsolute | |
+ * - join | |
+ * - relative | |
+ * - toNamespacedPath | |
+ * - dirname | |
+ * - basename | |
+ * - extname | |
+ * - format | |
+ * - parse | |
+ * - sep | |
+ * - delimiter | |
+ * - win32 | |
+ * - posix | |
+ */ | |
+import path from 'path' | |
+ | |
+/** | |
+ * GraphQL Nuxt Module. | |
+ * | |
+ * Notice we're returning a function because we want access to this. | |
+ */ | |
+export default function GraphQueryLanguageClientNuxtModule (moduleOptions = {}) { | |
+ // this.nuxt | |
+ // this.options | |
+ // this.requiredModules | |
+ | |
+ const options = this.options.apollo || moduleOptions | |
+ | |
+ const pathToPlugins = path.resolve(__dirname).replace(/modules/, 'plugins') | |
+ this.addPlugin(path.join(pathToPlugins, 'graphql-client.js')) | |
+ | |
+ // Add graphql loader | |
+ this.extendBuild((config, { | |
+ isServer, | |
+ }) => { | |
+ config.resolve.extensions = config.resolve.extensions.concat('.graphql', '.gql') | |
+ | |
+ const gqlRules = { | |
+ test: /\.(graphql|gql)$/, | |
+ use: 'graphql-tag/loader', | |
+ exclude: /(node_modules)/, | |
+ } | |
+ | |
+ if (options.includeNodeModules) { | |
+ delete gqlRules.exclude | |
+ } | |
+ | |
+ if (!config.module.rules.find(rule => rule.use === 'graphql-tag/loader')) { | |
+ config.module.rules.push(gqlRules) | |
+ } | |
+ if (isServer) { | |
+ // Adding proper way of handling whitelisting with Nuxt 2 | |
+ this.options.build.transpile.push(/^vue-cli-plugin-apollo/) | |
+ } | |
+ }) | |
+} | |
diff --git a/nuxt.config.js b/nuxt.config.js | |
index 9123d90..7198456 100644 | |
--- a/nuxt.config.js | |
+++ b/nuxt.config.js | |
@@ -76,0 +77 @@ export default { | |
+ '@/modules/graphql', | |
diff --git a/package.json b/package.json | |
index a945142..951cb11 100644 | |
--- a/package.json | |
+++ b/package.json | |
@@ -16 +15,0 @@ | |
- "@unify360/ui": "https://u360main.cangis.cgi.com:50043/Unify360/ui.git#semver:^0.1.12", | |
@@ -18,0 +18 @@ | |
+ "@unify360/ui": "https://u360main.cangis.cgi.com:50043/Unify360/ui.git#semver:^0.1.12", | |
@@ -21 +21 @@ | |
- "nuxt": "^2.0.0", | |
+ "nuxt": "^2.2.0", | |
@@ -25 +25,9 @@ | |
- "vuex-persistedstate": "^2.5.4" | |
+ "vuex-persistedstate": "^2.5.4", | |
+ "graphql": "^0.12.3", | |
+ "graphql-tag": "^2.10.0", | |
+ "vue-apollo": "^3.0.0-beta.25", | |
+ "apollo-client": "^2.4.1", | |
+ "vue-cli-plugin-apollo": "^0.17.0", | |
+ "apollo-cache-inmemory": "^1.2.9", | |
+ "apollo-link": "^1.0.3", | |
+ "apollo-link-http": "^1.2.0" | |
diff --git a/plugins/graphql-client.js b/plugins/graphql-client.js | |
new file mode 100644 | |
index 0000000..bd2abd9 | |
--- /dev/null | |
+++ b/plugins/graphql-client.js | |
@@ -0,0 +1,41 @@ | |
+/** | |
+ * Nuxt.js GraphQL integration plugin. | |
+ * | |
+ * Where we bind how Vue/Nuxt configuration from the Module. | |
+ * Partly copied from [1] | |
+ * | |
+ * [1]: https://github.com/nuxt-community/apollo-module/blob/master/lib/templates/plugin.js | |
+ */ | |
+ | |
+import Vue from 'vue' | |
+import VueApollo from 'vue-apollo' | |
+import { | |
+ createApolloClient, createApolloProvider, | |
+} from '@/utils/apollo-client-factory' | |
+ | |
+Vue.use(VueApollo) | |
+ | |
+export default async ({ | |
+ app, beforeNuxtRender, req, store, $axios, isHMR, | |
+}, inject) => { | |
+ const ApolloClient = createApolloClient() | |
+ const apolloProvider = createApolloProvider(ApolloClient) | |
+ app.apolloProvider = apolloProvider | |
+ | |
+ if (process.server) { | |
+ const ApolloSSR = require('vue-apollo/ssr') | |
+ Vue.use(ApolloSSR) | |
+ beforeNuxtRender(async ({ | |
+ Components, nuxtState, | |
+ }) => { | |
+ Components.forEach(Component => { | |
+ // Fix https://github.com/nuxt-community/apollo-module/issues/19 | |
+ if (Component.options && Component.options.apollo && Component.options.apollo.$init) { | |
+ delete Component.options.apollo.$init | |
+ } | |
+ }) | |
+ await ApolloSSR.prefetchAll(apolloProvider, Components, ctx) | |
+ nuxtState.apollo = ApolloSSR.getStates(apolloProvider) | |
+ }) | |
+ } | |
+} | |
diff --git a/utils/apollo-client-factory.js b/utils/apollo-client-factory.js | |
new file mode 100644 | |
index 0000000..c6570c4 | |
--- /dev/null | |
+++ b/utils/apollo-client-factory.js | |
@@ -0,0 +1,61 @@ | |
+/** | |
+ * Apollo Client wrapper. | |
+ * | |
+ * The client property should be an usable Apollo GraphQL client. | |
+ * As per graphql-client [1] | |
+ * | |
+ * [1]: https://github.com/Akryum/vue-cli-plugin-apollo/blob/master/graphql-client/src/index.js#L14 | |
+ * https://akryum.github.io/vue-apollo/guide/installation.html#vue-cli-plugin | |
+ */ | |
+ | |
+import { | |
+ InMemoryCache, | |
+} from 'apollo-cache-inmemory' | |
+import VueApollo from 'vue-apollo' | |
+import { | |
+ createApolloClient as createApolloClientFactory, | |
+} from 'vue-cli-plugin-apollo/graphql-client' | |
+ | |
+export const createApolloClient = opts => { | |
+ let clientConfig = {} | |
+ | |
+ clientConfig.tokenName = 'UserToken' | |
+ | |
+ const cache = Reflect.has(opts, 'cache') ? opts.cache : new InMemoryCache() | |
+ | |
+ clientConfig.ssr = !!process.server | |
+ if (!process.server) { | |
+ cache.restore(window.__NUXT__ ? window.__NUXT__.apollo.defaultClient : null) | |
+ } | |
+ | |
+ Object.keys(opts).forEach(key => Object.assign(clientConfig, Reflect.get(opts, key))) | |
+ | |
+ clientConfig.cache = cache | |
+ | |
+ let client = createApolloClientFactory({ | |
+ ...clientConfig, | |
+ }) | |
+ | |
+ client.apolloClient.wsClient = client.wsClient | |
+ | |
+ return client | |
+} | |
+ | |
+export const createApolloProvider = apolloInstance => { | |
+ let providerOptions = { | |
+ clients: {}, | |
+ } | |
+ providerOptions.defaultClient = apolloInstance.apolloClient | |
+ | |
+ const vueApolloOptions = Object.assign(providerOptions, { | |
+ errorHandler (error) { | |
+ console.log( | |
+ '%cError', | |
+ 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', | |
+ error.message | |
+ ) | |
+ }, | |
+ }) | |
+ | |
+ return new VueApollo(vueApolloOptions) | |
+} | |
-- | |
2.17.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment