Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try replacing lodash with deepmerge #126

Merged
merged 1 commit into from
Jul 25, 2019
Merged

Try replacing lodash with deepmerge #126

merged 1 commit into from
Jul 25, 2019

Conversation

bufke
Copy link
Collaborator

@bufke bufke commented May 27, 2019

Alternative fix for #123

This change gets the project on a better maintained package. lodash.merge is no longer maintained and suffers from a potential security vulnerability. lodash itself would increase the bundle size to an unacceptable level. Switching to deepmerge actually reduces the webpack bundle size by about 10k compared to lodash.merge.

Previously it was decided to avoid deepmerge due to observed issues when used with the project vuex-persist. This seems only to be unwanted array concatenation instead of replacement. It's easy to avoid this using options set to deepmerge, which this PR demonstrates.

Still this is a significant change and we cannot guarantee the behaviour will exactly match lodash.merge. If we decide to go with deepmerge, I recommend releasing a beta release and asking users to try this out before declaring it stable.

@btroncone
Copy link
Owner

This seems like a fair option to me. If others agree, I would be ok with cutting a beta release to test it out. 👍

@KlapTrap
Copy link

@btroncone We'll help out testing it whenever you're ready.

@btroncone
Copy link
Owner

@bufke Is this ready for beta?

@bufke
Copy link
Collaborator Author

bufke commented Jun 19, 2019

Yes ready for beta. Hopefully we can get more feedback before releasing as stable.

@bufke
Copy link
Collaborator Author

bufke commented Jul 24, 2019

@btroncone we have 3 👍 and no comments about any issues. Are we as ready as we'll ever be? This DEF merits a major version bump as the chance for very subtle differences is high. I may look into the Angular Universal pull request today too if we do a release any time soon.

@btroncone
Copy link
Owner

Cool, I’ll merge this in tonight and bump to v8.0. Thanks! 👍

@btroncone
Copy link
Owner

Merging 👍

@btroncone btroncone merged commit ac54e0e into master Jul 25, 2019
@StephenCooper
Copy link

StephenCooper commented Jul 29, 2019

The change to deepmerge means that objects in the state tree loose their function definitions. I have confirmed this behavior difference here .

export class MyClass {
  constructor(public a: string){}
  public getValue(){
    return this.a;
  }
}

export class State {
   toHydrate: MyClass;
}

Lodash Merge

var loState = {} as State;
loState = merge({}, loState, {toHydrate: new MyClass("Lodash merge")});
loState.toHydrate.getValue(); 
// returns Lodash merge

Deepmerge

var deepState = {} as State;
deepState = deepmerge(deepState, { toHydrate:new MyClass("Deep merge")});
deepState.toHydrate.getValue(); 
//Error: deepState.toHydrate.getValue is not a function

This breaks our code as an object in the initial state tree no longer has its methods after a re-hydration of a different property.

I can work around it by re-creating the objects myself on the @ngrx/store/update-reducers action within my own reducer.

case UPDATE: {
      return {
        ...state,
        toHydrate: new MyClass(state.toHydrate.a)
      }

I may also look at using a selector that creates the object and then just store a plain old javascript object in the store which would avoid this issue with deepmerge.

export const getClass = createSelector(
    getFeatureState,
    state => new MyClass(state.a)
);

Edit:
From: Redux FAQ

It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.

I will be updating our code to follow this advice and so deepmerge behavior is acceptable. :)

@bufke
Copy link
Collaborator Author

bufke commented Jul 29, 2019

This might be worth documenting. We could retroactively update the changlog about a known breaking change. @StephenCooper feel free to open a Pull Request clarifying the behavior if you have time.

@bufke
Copy link
Collaborator Author

bufke commented Jul 29, 2019

Added findings to changelog

BovineEnthusiast pushed a commit to beocommedia/ngrx-store-localstorage that referenced this pull request Oct 29, 2019
…lstorage

* 'master' of https://github.com/btroncone/ngrx-store-localstorage:
  Update CHANGELOG.md
  Update CHANGELOG.md
  chore(release): release version 8.0.0
  Try replacing lodash with deepmerge (btroncone#126)
  Update CHANGELOG.md
  chore(release): 7.0.1
  btroncone#129 updating peer dependencies
  Add Angular Universal support by checking if browserSide fix btroncone#73
@BBlackwo BBlackwo deleted the deepmerge branch April 18, 2020 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants