State management with GraphQL + Apollo
Problem to solve
Right now we're managing state with Vuex an it works pretty well. But the issue is Apollo offers its own way to store API calls results (Apollo cache) as well as local application state (apollo-link-state). There was a long discussion about best practices of combining GraphQL+Apollo with Vuex in vue-apollo repository: https://github.com/Akryum/vue-apollo/issues/140 (TL;DR: use apollo-link-state
).
As we're going to use GraphQL, we need to discuss the strategy of state management.
Target audience
Frontend Team
Further details
There are 4 main approaches to manage a state in application using GraphQL + Apollo:
-
keep Vuex as a single source of truth storing all data from API to state. In this case we don't need Apollo cache and we can disable it with fetchPolicy:
'no-cache'
property in Apollo config. We don't need vue-apollo as well because it's designed to make calls from component level and we're going to make them from Vuex actions. We use Apollo query which returns a Promise.Pros:
- we keep the flow familiar to the team;
- we can still save local application data to Vuex state;
- we get rid of one dependency;
Cons:
- we lose vue-apollo features;
- we don't leverage Apollo cache
- we can't use Apollo polling
-
again, keep Vuex as a single source of truth storing all data from API to state but enable Apollo cache. We don't need vue-apollo as well. This case differs from the first one: we use Apollo watchQuery which returns an Observable instead of Promise
Pros:
- we keep the flow familiar to the team;
- we can still save local application data to Vuex state;
- we get rid of one dependency;
- we can do polling simply passing
pollInterval
towatchQuery
Cons:
- we lose vue-apollo features again;
- we have data stored in both Vuex and Apollo cache.
-
make API calls from components and use Apollo cache to save results while keeping local state in Vuex. This approach has 2 sources of truth and it's the biggest flaw.
-
get rid of Vuex and use Apollo cache for storing API calls results and apollo-link-state for local application state.
Pros:
- this is the recommended way of doing things;
- we get rid of one dependency
Cons:
- the way to handle local state requires some boilerplate and is not very intuitive;
- there is no such thing as getters in Apollo state;
Proposal
I made a little proof of concept to compare both viable options. It contains 3 branches: 2 for Vuex implementations (one using queries as promises, no Apollo cache; second uses Observables with polling) and 1 for apollo-link-state.
Please have a look at implementation and consider what is the most convenient for you and why.