Vue-apollo: Support Vue 3.0 composition API

Created on 8 Jul 2020  路  19Comments  路  Source: vuejs/vue-apollo

According to the Vue roadmap, the API for v3.0 is now frozen.

enhancement v4

Most helpful comment

v4.0.0-alpha.10 is supposed to work with Vue 3 since it adds vue-demi to automatically toggle between @vue/composition-api (Vue 2) and Vue 3.

However, I've found a couple of issues with it: #1041 #1040

With those two changes I got it working. Until they are merged or refactored by Guillaume, you can try this patch:

// scripts/vue-apollo-patch.js

const fs = require('fs')
const path = require('path')

const loadTrackingPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/util/loadingTracking.js'
)

fs.writeFileSync(
  loadTrackingPath,
  fs.readFileSync(loadTrackingPath, 'utf8').replace(/\.\$root/m, '.root')
)

const useQueryPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/useQuery.js'
)

fs.writeFileSync(
  useQueryPath,
  fs
    .readFileSync(useQueryPath, 'utf8')
    .replace(/(^.*onServerPrefetch)/m, '$1=()=>{}; $1')
    .replace(/(.* require\("vue"\);)/m, '')
    .replace(/^.*(nextTick)/m, 'vue_demi_1.$1')
)

In package.json:

"scripts": {
  "postinstall": "node scripts/vue-apollo-patch.js"
}

Just make sure the paths in the script point to the right files (in case node_modules is not in the parent directory).

Hope that helps!

All 19 comments

This is really a major problem. We had to move many projects to react during the last month, because we were not able to go with vue 3. We did many poc and in general vue3 was doing already great. Just the missing graphql and some typescript problems killed the approach.

vue-apollo v4 has been available since early December 2019, with v4.0.0-alpha.10 having been released 2 days ago.

vue-apollo v4 has been available since early December 2019, with v4.0.0-alpha.10 having been released 2 days ago.

True, but this doesn't support Vue 3, just Vue 2 with the composition api plugin.

From my understanding it can be used with vue 3. Have you tested, @justinwaite?

I do use it with composition api because storybook is the last thing holding me back from upgrading to vue 3. So I've not tested myself, but I believe it is compatible in the latest version.

Its latest version was released with using a package which allows vue apollo 4 to be used with either vue 2 or vue 3.

@MechJosh0 there may be multiple things at play here, but I am unable to get it working with Vue 3 + Vite. See my comment here: https://github.com/vuejs/vue-apollo/issues/1029#issuecomment-670064383

It does work with Composition API but the thing is that it only does up to [email protected] (see issue here). I had v4.0.0-alpha.8 and [email protected] working fine.

However, it gives this error after upgrading to v4.0.0-alpha.10
[vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function

From what I can tell at least @vue/apollo-composable use features of the composition-api/Vue2 that are simply not available in Vue3 (onServerPrefetch/serverPrefetch, vm.$isServer). I can't find much regarding Vue3 SSR so I don't think there's a 1-to-1 replacement for the SSR API.

v4.0.0-alpha.10 is supposed to work with Vue 3 since it adds vue-demi to automatically toggle between @vue/composition-api (Vue 2) and Vue 3.

However, I've found a couple of issues with it: #1041 #1040

With those two changes I got it working. Until they are merged or refactored by Guillaume, you can try this patch:

// scripts/vue-apollo-patch.js

const fs = require('fs')
const path = require('path')

const loadTrackingPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/util/loadingTracking.js'
)

fs.writeFileSync(
  loadTrackingPath,
  fs.readFileSync(loadTrackingPath, 'utf8').replace(/\.\$root/m, '.root')
)

const useQueryPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/useQuery.js'
)

fs.writeFileSync(
  useQueryPath,
  fs
    .readFileSync(useQueryPath, 'utf8')
    .replace(/(^.*onServerPrefetch)/m, '$1=()=>{}; $1')
    .replace(/(.* require\("vue"\);)/m, '')
    .replace(/^.*(nextTick)/m, 'vue_demi_1.$1')
)

In package.json:

"scripts": {
  "postinstall": "node scripts/vue-apollo-patch.js"
}

Just make sure the paths in the script point to the right files (in case node_modules is not in the parent directory).

Hope that helps!

Thanks @frandiox

v4.0.0-alpha.10 is supposed to work with Vue 3 since it adds vue-demi to automatically toggle between @vue/composition-api (Vue 2) and Vue 3.

However, I've found a couple of issues with it: #1041 #1040

With those two changes I got it working. Until they are merged or refactored by Guillaume, you can try this patch:

// scripts/vue-apollo-patch.js

const fs = require('fs')
const path = require('path')

const loadTrackingPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/util/loadingTracking.js'
)

fs.writeFileSync(
  loadTrackingPath,
  fs.readFileSync(loadTrackingPath, 'utf8').replace(/\.\$root/m, '.root')
)

const useQueryPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/useQuery.js'
)

fs.writeFileSync(
  useQueryPath,
  fs
    .readFileSync(useQueryPath, 'utf8')
    .replace(/(^.*onServerPrefetch)/m, '$1=()=>{}; $1')
    .replace(/(.* require\("vue"\);)/m, '')
    .replace(/^.*(nextTick)/m, 'vue_demi_1.$1')
)

In package.json:

"scripts": {
  "postinstall": "node scripts/vue-apollo-patch.js"
}

Just make sure the paths in the script point to the right files (in case node_modules is not in the parent directory).

Hope that helps!

The quoted reply fails because the onServerPrefetch property can't be resigned on a freezed object. The below snippet solves the issue:

const fs = require('fs')
const path = require('path')

const loadTrackingPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/util/loadingTracking.js'
)

fs.rmdirSync(path.resolve(__dirname, '../node_modules/.vite_opt_cache'), {
  recursive: true
})

fs.writeFileSync(
  loadTrackingPath,
  fs.readFileSync(loadTrackingPath, 'utf8').replace(/\.\$root/m, '.root')
)

const useQueryPath = path.resolve(
  __dirname,
  '../node_modules/@vue/apollo-composable/dist/useQuery.js'
)

fs.writeFileSync(
  useQueryPath,
  fs
    .readFileSync(useQueryPath, 'utf8')
    .replace(/(^.*onServerPrefetch)(\.\?\.)?/m, '$1?.')
    .replace(/(.* require\("vue"\);)/m, '')
    .replace(/^.*(nextTick)/m, 'vue_demi_1.$1')
)

It does work with Composition API but the thing is that it only does up to [email protected] (see issue here). I had v4.0.0-alpha.8 and [email protected] working fine.

However, it gives this error after upgrading to v4.0.0-alpha.10
[vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function

For me this issue got resolved by putting Vue.use(VueCompositionAPI) into an external file (the same one where I'm setting up Apollo) and then importing it in the main.{ts,js}

Full support for Vue 3 is pending the inclusion of onServerPrefetch (currently Vue 3 only has serverPrefetch as a Component option).

@Akryum Could you please release v4.0.0-alpha.11 with the latest updates? It should make it work for SPAs at least since all the changes related to this patch are already merged. Thanks!

Vue 3 support for @vue/apollo-composable is now included in automatic tests on v4 branch. (More tests to come)

Updated patch for v4.0.0-alpha.12 to make Vite happy:

const fs = require("fs")
const path = require("path")

fs.rmdirSync(path.resolve(__dirname, "../node_modules/.vite_opt_cache"), {
  recursive: true,
})

const useQueryPath = path.resolve(
  __dirname,
  "../node_modules/@vue/apollo-composable/dist/useQuery.js"
)

fs.writeFileSync(
  useQueryPath,
  fs.readFileSync(useQueryPath, "utf8").replace(/^onServerPrefetch, /mu, "")
)

Updated patch to fully remove onServerPrefetch to make it work with vite.

vite: 1.0.0-rc4
vue: 3.0.2
graphql: 15.3.0
@apollo/client: 3.2.5
@vue/apollo-composable: 4.0.0-alpha.12

const fs = require("fs")
const path = require("path")

fs.rmdirSync(path.resolve(__dirname, "../node_modules/.vite_opt_cache"), {
  recursive: true,
})

const useQueryPath = path.resolve(
  __dirname,
  "../node_modules/@vue/apollo-composable/dist/useQuery.js"
)

const vueApolloComposablePath = path.resolve(
  __dirname,
  "../node_modules/@vue/apollo-composable/dist/vue-apollo-composable.js"
)

fs.writeFileSync(
  useQueryPath,
  fs.readFileSync(useQueryPath, "utf8").replace(/^onServerPrefetch, /mu, "")
)

fs.writeFileSync(
  useQueryPath,
  fs.readFileSync(useQueryPath, "utf8").replace(/onServerPrefetch === null.*?\}\);/mus, "")
)

fs.writeFileSync(
  vueApolloComposablePath,
  fs.readFileSync(vueApolloComposablePath, "utf8").replace(/vue_demi_5.onServerPrefetch === null.*?\}\);/mus, "")
)

This is what ended up working for me

const fs = require("fs");
const path = require("path");

const loadTrackingPath = path.resolve(
  __dirname,
  "../node_modules/@vue/apollo-composable/dist/util/loadingTracking.js"
);

fs.rmdirSync(path.resolve(__dirname, "../node_modules/.vite_opt_cache"), {
  recursive: true
});

fs.writeFileSync(
  loadTrackingPath,
  fs.readFileSync(loadTrackingPath, "utf8").replace(/\.\$root/m, ".root")
);

const useQueryPath = path.resolve(
  __dirname,
  "../node_modules/@vue/apollo-composable/dist/useQuery.js"
);

fs.writeFileSync(
  useQueryPath,
  fs
    .readFileSync(useQueryPath, "utf8")
    .replace(/\:\sonServerPrefetch\(/, ": (() => {})(")
    .replace(/(.* require\("vue"\);)/m, "")
);

it's not working for me with my version
"@apollo/client": "^3.2.9",
"@vue/apollo-composable": "^4.0.0-alpha.12",
"core-js": "^3.6.5",
"graphql": "^15.4.0",
"react": "^17.0.1",
"vue": "^3.0.0",

and still get this error can anyone tell me what should i do with this error

 ERROR  Failed to compile with 1 errors                                                                                                             1:59:59 PM

 error  in ./node_modules/@vue/apollo-composable/dist/useQuery.js

Module parse failed: Unexpected token (14:10)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import { ref, isRef, computed, watch, 
| // @ts-expect-error
> vue_demi_1.nextTick, } from 'vue-demi';
| import { throttle, debounce } from 'throttle-debounce';
| import { useApolloClient } from './useApolloClient';

 @ ./node_modules/@vue/apollo-composable/dist/index.js 1:0-39 1:0-39
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.0.198:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

@seyhadot not sure, you could create a new issue. Here's a small working app you can use to try to reproduce with: https://github.com/GraphQLGuide/guide-vue/tree/repro-1116

Was this page helpful?
0 / 5 - 0 ratings