Giter VIP home page Giter VIP logo

Comments (23)

Akryum avatar Akryum commented on April 27, 2024 1

We can start playing with SSR! v2.1.0-beta.1

from apollo.

Akryum avatar Akryum commented on April 27, 2024 1

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.

Akryum avatar Akryum commented on April 27, 2024

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.

Akryum avatar Akryum commented on April 27, 2024

More could be done to improve compatibility with the server, if you have any idea please don't hesitate to share them.

from apollo.

marutypes avatar marutypes commented on April 27, 2024

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.

matteodem avatar matteodem commented on April 27, 2024

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.

marutypes avatar marutypes commented on April 27, 2024

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.

matteodem avatar matteodem commented on April 27, 2024

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.

Akryum avatar Akryum commented on April 27, 2024

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.

matteodem avatar matteodem commented on April 27, 2024

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.

marutypes avatar marutypes commented on April 27, 2024

I'm basically doing that manually atm, and it mostly works, as long as my queries only care about route parameters :/

from apollo.

Akryum avatar Akryum commented on April 27, 2024

Maybe I could fake this and the data hook, sort of.

from apollo.

matteodem avatar matteodem commented on April 27, 2024

@TheMallen can you show us the code where you use apolloState on the client-side?

from apollo.

Akryum avatar Akryum commented on April 27, 2024

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.

Akryum avatar Akryum commented on April 27, 2024

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.

matteodem avatar matteodem commented on April 27, 2024

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.

Akryum avatar Akryum commented on April 27, 2024

It may not do that in the first iteration, but that would be nice to have indeed. 😄

from apollo.

matteodem avatar matteodem commented on April 27, 2024

I think having that function would already greatly simplify the server side pre fetching. Any way of helping you with this?

from apollo.

Akryum avatar Akryum commented on April 27, 2024

I think we will need to walk the possible tree of components like what react-apollo does.

from apollo.

matteodem avatar matteodem commented on April 27, 2024

I'll definitely check out the SSR this weekend.

from apollo.

Akryum avatar Akryum commented on April 27, 2024

Mostly final SSR API has landed in beta.8!

from apollo.

dohomi avatar dohomi commented on April 27, 2024

@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.

dohomi avatar dohomi commented on April 27, 2024

@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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.