store icon indicating copy to clipboard operation
store copied to clipboard

WIP feat: lazy loaded reducers

Open smithad15 opened this issue 8 years ago • 15 comments

This is the beginning thoughts for how to address the ability to be able to load reducers into your state piecemeal if you are using a nested NgModule application structure and also to be able to lazy load parts of your state if you so wish.

I chose the forRoot / forChild paradigm to start considering other work in the Angular ecosystem like @angular/router. This could also be done simply with NgRedux.configureStore and the new NgRedux.addReducers if that's more desirable for the public API.

Still TODO:

  • [ ] Verify provider functionality with angular-redux/example-app
  • [ ] Determine whether changes need to be made to the mock/testing utilities
  • [ ] Add an article describing how to accomplish lazy loading to the docs

smithad15 avatar Jun 01 '17 20:06 smithad15

@e-schultz @SethDavenport @danielfigueiredo @rpdasilva thoughts and comments appreciated

smithad15 avatar Jun 01 '17 20:06 smithad15

@smithad15 if I'm understanding this correctly - this doesn't need to be a breaking change - as the old way of configuring a store still works? - matter of putting it in the 6.x branch vs 7.x

Some things I've wondered though when it comes to lazy-loading reducers are:

  • What if an action gets dispatched that you expect to be handled by a reducer that will be lazy loaded, but isn't loaded yet? - if you keep to the pattern of any action creators that are part of this, get lazy loaded at that time - and the reducer doesn't handle actions that are not part of this, it's not an issue.

  • What about use-cases for middleware - although if using something like redux-observable, they already have ways to adding new epics async

For general middleware (loggers, etc) - I see them being app-wide and this isn't an issue, and for things like epics - there are ways of doing this, and I guess just ensuring that things like epics get added before the reducers/actions get dispatched? - this might be a non-issue, and simply a matter of documentation and not something that needs to be baked into the code. Just something to think about

e-schultz avatar Jun 02 '17 16:06 e-schultz

@e-schultz Yes, this is not a breaking change and can be put into 6.x as it is still compatible with the existing way of configuring the store. The only thing it might break is if someone was upgrading from when we still used forRoot (maybe v4? Can't remember). That was removed around the beginning of the new year from my memory so I think there has been a reasonable amount of time to resolve that concern.

I've had thoughts about the same things (actions, middleware, etc.):

  • For actions dispatched before the reducer is loaded, I think this just falls under the usual "foot-guns" of lazy-loading anything. If it's a pattern that you are choosing to implement, then to me it's up to the developer to make sure they are handling the increased complexity that comes with it. This allows you to do it, how or whether you should do it is a bit of a predicate conversation.

  • In regards to middleware, I briefly entertained the thought of including a helper for loading epics with this library (your exploratory work with an epic loading decorator was the ignition point for that), however it didn't quite feel right at this moment as it would add another dependency. This pattern could be extended to handle that feature in the future if desired though. If the middleware allows for lazy-loading, then there is usually enough ability for the developer to handle that how they see fit. I don't foresee any issues with global middleware, but of course I'll test out that theory with the example application.

TLDR; Yes to much documentation 🙂

smithad15 avatar Jun 02 '17 18:06 smithad15

My main concerns here are:

  1. overlap with the logic behind configureSubStore which allows a form of lazy-loaded reducers anyway, and
  2. I'm not sure we should tie it directly to NgModule.

If I were to do this I would instead be inclined to add something like NgRedux.addReducer(reducer:Reducer , basePath:? PathSelector) that relevant components could call at any time, independent of how the module stuff works.

We could then generalize the composeReducers logic currently in fractal-reducer-map.ts to make this a special case of the fractal stuff where the basePath is in fact empty.

I feel that this would:

  • not change the init API as much
  • result in less code
  • decouple reducer registration from NgModule completely, resulting in a more granular ability to load reducers.

SethDavenport avatar Jun 06 '17 20:06 SethDavenport

I'm up for removing the NgModule related parts. I'll look into refactoring the subStore things into the feature as described, but my main concern was that I didn't actually want to scope added reducers like they are with subStores. The idea was to have them globally available. I'll look into this more as I feel like maybe I don't currently have a full grasp of the subStore implementation.

smithad15 avatar Jun 07 '17 14:06 smithad15

While there is overlap with configureSubStore - what about use cases where once the lazy-loaded thing is mounted - you don't want to limit the actions/etc it receives to be for that slice?

Thinking in terms of a large application - say, each 'tab' is a major feature - lazy load it once you navigate to it, but once there - there is a mix of 'global app state/actions' and 'feature state/actions'.

For example - navigate over to the profile section, change your user name - the app-wide session state needs to get updated.

But, I guess if the basePath is null/undefined - it wouldn't be an issue.

When putting it into a component with configureSubStore, and not in ngModule - what happens then if a person navigates away from that feature, then navigates back? The component gets destroyed/recreated - for the fractalState stuff this makes sense, but when thinking in terms of "sub-apps/large features" - does it make sense?

e-schultz avatar Jun 07 '17 14:06 e-schultz

@SethDavenport Had a chance to update the PR on top of your recent changes and also removing the NgModule bits. I think the configureSubStore logic doesn't quite match up to the use case I'm looking for, but I might be misreading it as well. Next step is still putting together a PR for the example app to showcase the usage pattern.

smithad15 avatar Jun 26 '17 13:06 smithad15

#453 can you implement ??

RSginer avatar Aug 02 '17 19:08 RSginer

Hey, this has slightly fell off my radar - I'm hoping to get some time soon to revisit a few things - but not opposed to getting this in soon, just a matter of time right now.

e-schultz avatar Aug 02 '17 20:08 e-schultz

Any good news regarding this one? I really would like to see this implemented.

Mockly avatar Sep 12 '17 09:09 Mockly

@smithad15 hey - since you were doing the initial work on this - I've lost track of where we were. Do you have time to revisit this again and see if we can get a release done with this feature?

e-schultz avatar Sep 20 '17 15:09 e-schultz

I believe @SethDavenport wanted to take a look at refactoring this to include some of the subStore code last we spoke. Documentation and examples still outstanding. Haven’t had much OSS time available as of late, but will try and push the examples and docs portions forward just to confirm that we all like the patterns and use-cases

smithad15 avatar Sep 21 '17 00:09 smithad15

What's the progress on this please? (I have an enterprise app where features are lazily loaded and each will have it's own set of reducers which need to be added to existing reducers when specific feature lazily loads).

Alternatively, can I somehow use replaceReducers or configureSubstore functionality for this? An example would be extremely useful :)

adamlubek avatar Oct 30 '17 13:10 adamlubek

Is this dead now? I would really like this functionality as well. I have a lazy-loaded module that carries with it a lot of data management code, and currently it all gets included in the main module because I can't seem to figure out how to lazy-load the reducer.

danimalia avatar Mar 29 '18 14:03 danimalia

@smithad15 I'm fine with your approach. I'm not going to be refactoring anything any time soon. It's probably not worth the waiting for me since I'm a bit out of the loop on recent Angular changes.

SethDavenport avatar Apr 01 '18 13:04 SethDavenport