apollo-link-state icon indicating copy to clipboard operation
apollo-link-state copied to clipboard

Is it possible to lazy load resolvers?

Open goldenbearkin opened this issue 6 years ago • 14 comments

First, Apollo link state is mind-blowing. Once start to use it, don't really want to go back to 'redux-nish' store anymore.

I am working on angular which out of the box provide router-based lazy loading feature. Ngrx which is kind of de facto state management for angular application, also supports lazy loading feature. As a result Angular with ngrx power the fully modularized application structure.

Apollo link state is an awesome library which will be definitely capable of replacing ngrx. Would the lazy loading feature be possible in apollo-link-state or would it be on the road map?

goldenbearkin avatar Jan 22 '18 18:01 goldenbearkin

Hey! Thanks for the awesome feedback, I'm glad you're loving apollo-link-state so far 🎉

Right now, you can lazily write defaults to the store (just call cache.writeData with your initial state once you transition routes), but there's no way of lazily adding resolvers to your resolver map. Have you experienced any performance issues by specifying all your resolvers up front?

peggyrayzis avatar Jan 22 '18 20:01 peggyrayzis

We haven't experienced any performance issues since our application is still in very early stage. Right now we have several teams working on different features of a single application and these features are lazy loaded on demand in order to keep the initiate bundle small. In order to allow the teams work independently, we are looking for the solution of having distributed resolver map or even to be able to lazy load and then concat the resolver map when the corresponding features are lazy loaded.

More than 30% of our application logic is related to local stage and we don't want the initiate bundle getting larger as the application logic is getting complicated.

BTW, @peggyrayzis I like your talks/blogs very much and looking forward to your next new idea of Apollo stack. :muscle:

goldenbearkin avatar Jan 23 '18 07:01 goldenbearkin

Lazy loading would be a very impactful addition to apollo-link-state for large teams or modular projects. For instance, in our application every page is lazy loaded (the same rings true for large projects such as Google Cloud Platform which is built on angular). Having feature-specific state logic living with the features is key to separating concerns with different aspects of an application! Would be cool to see this implemented.

justinwaite avatar Jan 31 '18 00:01 justinwaite

Just adding my two cents.

I agree with @goldenbearkin and @jdeanwaite I was actually having a similar discussion on the apollo-angular repo regarding lazy loading.

I have also been reading up issues on the main apollo-client repo. In particular this thread for the main apollo-client module seems to imply schema stitching is what the team prefers.

I think this issue might be better placed in that repo, as if you could be lazy when schema stitching into the main client, this repo would not need to change.

My thoughts:

This is a snippet from my current client setup for Apollo-Angular

    const cache = new InMemoryCache();
    const remoteHttpLink = httpLink.create({uri});

    const stateLinkConfig = {
      cache,
        defaults: {
    ...themeDefault,
    ...searchQueryDefault
    },
      resolvers: {
        Mutation: {
        ...themeResolverMutation,
        ...searchQueryResolverMutation,
        }
      },
    };

    const stateLink = withClientState(stateLinkConfig);

    const apolloLink = ApolloLink.from([
      stateLink,
      remoteHttpLink,
    ]);

    apollo.create({
      link: apolloLink,
      cache: cache,
    });

Not sure exactly how this would work, but as ApolloLink.from takes an array:

    const apolloLink = ApolloLink.from([
      stateLink,
      remoteHttpLink,
    ]);

It would be great if you could push/concat extra items into the apollo client asynchronously after creation, something like this:

    //totally made up code
    const stateLinkConfig2 = {
      cache,
        defaults: {
    ...theme2Default,
    },
      resolvers: {
        Mutation: {
        ...theme2ResolverMutation,
        }
      },
    };

apollo.link.concat(ApolloLink.from([stateLinkConfig2])

@peggyrayzis, @goldenbearkin, @jdeanwaite What do you think, should we open this as issue on the main repo?

vespertilian avatar Feb 07 '18 02:02 vespertilian

@vespertilian I like the idea, though I think adding to the existing link chain may present some issues. For example, I know there are scenarios where the order of the links matter, so if you have a link that should go last and then a lazy-loaded state link is added to the end that could cause undesired behaviors. I think if we could maintain a single link for apollo-link-state and be able to aggregate resolvers onto that, that could be better. Thoughts?

justinwaite avatar Feb 16 '18 19:02 justinwaite

@jdeanwaite

Sure, I mean it's primarily the internal state resolvers and mutations I want to have lazy loaded.

Is this what you were thinking?

    const cache = new InMemoryCache();
    const remoteHttpLink = httpLink.create({uri});

    const stateLinkConfig = {
      cache,
        defaults: {
    ...themeDefault,
    ...searchQueryDefault
    },
      resolvers: {
        Mutation: {
        ...themeResolverMutation,
        ...searchQueryResolverMutation,
        }
      },
    };

    const stateLink = withClientState(stateLinkConfig);

    const apolloLink = ApolloLink.from([
      stateLink,
      remoteHttpLink,
    ]);

    apollo.create({
      link: apolloLink,
      cache: cache,
    });

    //totally made up code that would be lazy loaded
    const stateLinkConfig2 = {
      cache,
        defaults: {
    ...theme2Default,
    },
      resolvers: {
        Mutation: {
        ...theme2ResolverMutation,
        }
      },
    };

    stateLink.mergeConfig(stateLinkConfig2)

vespertilian avatar Feb 17 '18 00:02 vespertilian

@vespertilian Yeah something like that! Basically a way to merge in the resolvers and ensure that any new defaults get written. Something like this would be super useful, though I'm not 100% sure how easy it is to implement. Including ApolloModule in a lazy loaded module is trouble enough as it is (forced to use an injection token).

justinwaite avatar Feb 17 '18 08:02 justinwaite

Hey! Thanks for your patience. I'm considering adding a way to dynamically load resolvers and defaults for the 1.0 release. I'd love your feedback once I spec it out. 😀

peggyrayzis avatar Mar 15 '18 15:03 peggyrayzis

Hey @peggyrayzis just let me know when you have something to look at. Happy to help in any way I can.

vespertilian avatar Mar 16 '18 03:03 vespertilian

@peggyrayzis sounds great! Look forward to seeing progress on this.

justinwaite avatar Mar 17 '18 07:03 justinwaite

Any news or a workaround on this? Thx

ceelian avatar Dec 08 '18 06:12 ceelian

@peggyrayzis Also keen to help on this - excited by the idea of lazy-loading resolvers.

mattpocock avatar Dec 27 '18 11:12 mattpocock

As I understand the new feature of the apollo-client of adding resolvers dynamically, as mentioned in https://github.com/apollographql/apollo-client/pull/4338, this will make lazy loading available.

ceelian avatar Jan 22 '19 08:01 ceelian

Any good examples out there to demonstrate how lazy loading resolvers work?!

JayKan avatar Mar 13 '19 22:03 JayKan