Comments (23)
We can start playing with SSR! v2.1.0-beta.1
from apollo.
Here are some brainstorming about how it may look like (I didn't test it yet, but if someone has time, he can 😄).
from apollo.
apollo-client needs fetch
to run. Since it is only available in a browser, try installing node-fetch and exposing it globally:
import fetch from 'fetch'
global.fetch = fetch
See #13
from apollo.
More could be done to improve compatibility with the server, if you have any idea please don't hesitate to share them.
from apollo.
I already am using fetch
on the server. My problem is that as it is you can't actually have your components defer rendering until they have data, so you end up with no data if your render is faster than the fetch, or alternatively trying to run the queries manually without component instances.
I have something sort of kind of working now using the following code, but it's limited to queries that don't have any dynamic variables (since we don't have a this
context when we try to run them)
// server-entry.js
// Apollo in this context is a wrapper I made around apollo client that sets some api credentials for my app
export default (context) => {
// set session to our passed in express session data
if (context.session) {
store.commit('setSession', context.session);
const {accessToken, shop} = store.state.session;
console.log(context);
Vue.use(VueApollo, {
apolloClient: Apollo.init(accessToken).client(),
ssrMode: true,
});
}
// set router's location
router.push(context.url);
return Promise
.all(router.getMatchedComponents().map((component) => {
/* `component` in this function is the definition, not an instance.
Any methods we run on it (for example, `variables` will not have access to
real props or anything like that*/
if (component.apollo && Apollo.client()) {
const dataDependencies = component.apollo;
/* if we have a vue-apollo field manually run the query.
We don't have a this context so we have to do it pretty naively */
const queries = Object.keys(dataDependencies)
.map((key, index) => {
const definition = dataDependencies[key];
return Apollo.client().query({query: definition.query || definition}); // this could obviously be better but it works for now
});
return Promise.all(queries);
}
return null;
}))
.then(() => {
console.log(`data pre-fetch: ${Date.now() - startTime}ms`);
// the request handler will inline the state in the HTML response.
context.initialState = store.state;
if (Apollo.client()) {
context.apolloState = Apollo.client()
.store
.getState()
.apollo;
}
return app;
});
Then we inline context.apolloState
inside of our render function and use it to hydrate initialState
on the client.
This works for queries that only depend on the route and store and other top level app information. If there is any way to perform asynchronous operations inside a lifecycle hook or otherwise defer component renderering from a plugin you could potentially check Vue.$isServer
in a hook and have DollarApollo
do it's magic there, but I've yet to turn up anything like that.
If I'm overthinking this and you have a working ssr example please let me know.
from apollo.
Ran into the same problem. Isn't the easiest solution to not load any data from graphql on the server and make sure inside the library that both server and client render the same html?
If the loadingKey
property is consistent this issue is pretty much resolved for me.
from apollo.
Ran into the same problem. Isn't the easiest solution to not load any data from graphql on the server
Unfortunately, that's an unacceptable solution for our app. If that's the best we can do I'll probably have to recommend we use react instead.
For now I'm using my solution above where I manually run what queries I can without access to the live instances, we'll see how far that gets me :/
from apollo.
Okay, yeah makes sense. I'm not sure how much of this logic should be part of this library, because server side vuejs still requires quite a lot of boilerplate code and it doesn't seem like there's an "official way" to do things (see hackernews vue clone).
Maybe it makes sense to kickstart a discussion on apollo-client? Unless there's already a solution on apollo level that I don't know about.
from apollo.
I'm exploring solutions for vue-apollo that would make server-side querying easy. If you have suggestions, please feel free to share!
from apollo.
wouldn't it be cool to have something like:
export default {
...
preFetch(store) {
return this.$apollo.initialize();
}
...
};
Which would return a promise that resolves after a client.query
and succesful instantiation of the data? In the hackernews
example they use the vuex store to instantiate the client with the data. But like shown in the example by @TheMallen we could also have some custom serialized state.
Btw ignore the wording, should be called something more descriptive (instead of initialize
)
from apollo.
I'm basically doing that manually atm, and it mostly works, as long as my queries only care about route parameters :/
from apollo.
Maybe I could fake this
and the data hook, sort of.
from apollo.
@TheMallen can you show us the code where you use apolloState
on the client-side?
from apollo.
What do you think of this?
export function prefetch(router) {
return Promise.all(router.getMatchedComponents().map(component => component.$apollo.promise.allQueries))
}
With $apollo.promise.allQueries
being a promise resolved when all the queries are resolved.
from apollo.
Another proposition (for instance-less use-case):
export default {
apollo: {
someData: {
query: ...,
variables () {
...
},
prefetchVariables: context => {
...
},
}
}
}
// vue-apollo API
export function prefetchQueries (componentDefinition, context) {
return Promise.all(...)
}
export function prefetchAll (router, context) {
return Promise.all(router.getMatchedComponents().map(component => prefetchQueries(component, context)))
}
from apollo.
Looks cool. Would apollo take over the serialization process or how would that work? As in how would we be able to instantiate the vue apollo instance with data on the client?
from apollo.
It may not do that in the first iteration, but that would be nice to have indeed. 😄
from apollo.
I think having that function would already greatly simplify the server side pre fetching. Any way of helping you with this?
from apollo.
I think we will need to walk the possible tree of components like what react-apollo does.
from apollo.
I'll definitely check out the SSR this weekend.
from apollo.
Mostly final SSR API has landed in beta.8
!
from apollo.
@Akryum great news. Was looking for the beta.8 release, did you publish it already? The improvements seem to make a working example now for nuxt
as far I could read?
from apollo.
@Akryum just found the npm release, I've been confused because this repo does not show a release note for beta.8.
from apollo.
Related Issues (20)
- Remove automatic subscription retry on error
- Can't receive messages in a chat using subscription
- skip() doesn't skip query HOT 1
- @vue/apollo-ssr doesn't work in SSR mode
- Fragments aren't returned in results when using useQuery/useLazyQuery reactive refs HOT 2
- Using vue-apollo-composable inside a Pinia setup store HOT 2
- `useApolloClient` checks wrong conditions before calling `inject()`
- useQuery blocks page load on 4.0.0 HOT 2
- useQuery with fetchPolicy: cache-only does not return expected data HOT 3
- Doesn't update the data after a mutation if `enabled` is `false` in `useQuery`
- Queries are not executed in given order
- @vue/[email protected] has a peer dependency conflict with Vue 3 HOT 4
- [docs] The installation guide is very bad HOT 1
- Refetch with New Variables Overrides Other Existing Refetches HOT 1
- `onBeforeUnmount` hook in `useQuery` is undesirable when used in pinia store HOT 1
- [Documentation] Composition API + Options API Configuration, how to make it work together? HOT 2
- Updating the `variables` ref does not work when using the function form
- Production breaks, dev mode works (Apollo client with id default not found.) HOT 3
- onResult does not fire on the first load of useLazyQuery HOT 5
- @vue/apollo-option - memory leak on SSR render
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apollo.