Skip to content

Commit

Permalink
redux-persist: Stop saving REHYDRATE payload to disk.
Browse files Browse the repository at this point in the history
The expensive part of persisting the state to disk is running
`stringify` (see replaceRevive.js). While zulip#4348 brought this time
from almost 2000ms down to, perhaps, 300ms on one account on my
device [1], that's still a long time, especially for work that
doesn't need to be done.

See discussion [2] for how we arrived at this solution.

[1] https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/.60remotedev-serialize.60.20and.20.60jsan.60/near/1083700
[2] https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/.60remotedev-serialize.60.20and.20.60jsan.60/near/1089466
  • Loading branch information
chrisbobbe authored and gnprice committed Jan 1, 2021
1 parent dc0b318 commit 08b77bb
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/third/redux-persist/createPersistor.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,12 @@ export default function createPersistor (store, config) {
rehydrate: adhocRehydrate,
pause: () => { paused = true },
resume: () => { paused = false },
purge: (keys) => purgeStoredState({storage, keyPrefix}, keys)
purge: (keys) => purgeStoredState({storage, keyPrefix}, keys),

// Only used in `persistStore`, to force `lastState` to update
// with the results of `REHYDRATE` even when the persistor is
// paused.
_resetLastState: () => { lastState = store.getState() }
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/third/redux-persist/persistStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,34 @@ export default function persistStore (store, config = {}, onComplete) {
}
try {
store.dispatch(rehydrateAction(restoredState, err))

// Ensure the payload of `REHYDRATE` isn't persisted.
//
// The `REHYDRATE` payload contains exactly every useful
// piece of state; there's nothing useful in the existing
// state before it arrives that it has to merge with. Since
// the `REHYDRATE` payload comes from the disk, there's no
// reason we'd want go and save it *back* to the disk when
// `REHYDRATE` arrives.
//
// Part of the work for preventing that is already done;
// `.pause()` is called on `persistor` above, and
// `.resume()` is called after. This does mean that
// persisting `REHYDRATE`'s payload isn't triggered directly
// on `REHYDRATE`. And yet, it is triggered on a
// *subsequent* action, because, upon each action, the
// persistor compares a piece of `lastState` to the
// corresponding piece of `state` to check whether that
// piece needs to be persisted -- and, on an action just
// after `REHYDRATE`, `lastState` is stale, containing the
// pre-`REHYDRATE` state. That's because `lastState` doesn't
// naturally update when the persistor is paused.
//
// So, fix that by still resetting `lastState` with the
// result of `REHYDRATE` when the persistor is paused; we
// can do that because we've exposed `_resetLastState` on
// the persistor.
persistor._resetLastState()
} finally {
complete(err, restoredState)
}
Expand Down

0 comments on commit 08b77bb

Please sign in to comment.