-
Notifications
You must be signed in to change notification settings - Fork 801
How React Hot Loader works
React-Hot-Loader was created to solve 2 tasks:
- Seamlessly replace the old Components, by the new ones.
- Hide all updates from React, to not let him remount changed branches, and thus drop the information stored in component instances, e.g state.
To achieve these goals React-Hot-Loader
- first detects which "old" components shall be replaced by which new ones.
- swaps the real code "behind" the components.
This step works in 2.5 different ways.
1.1. Babel plugin "registering" all top level variables using key as fileName+variableName
. If "something else" got registered by the same time - system will create a swap-pair. This is the only case, when you can replace anything by anything. Does not work with HoC, decorators and component/function composition, as long only a little part of a result is exposed as a top level variable
.
1.2. Hot-replacement render_. After RHL detects code update it start proccess we called hot-render.
- RHL hydrates the old react tree, starting in the current component (the one who detects the update)
- RHL start rendering react-tree, comparing the three resulting from a render and a hydrated one.
- If component on the "left", is not equal to the component on the "right", but looks quite similar - RHL creates swap-pair.
- quite similar means - the same displayName, and levensteinDistance between the old and the new code is not far that 20%.
Thus means that some big refactoring could lead to remount, as long RHL will not accept the new Component. In the future we might drop this comparison, and relay only on displayName, in case it is unique enought.
1.3 (1.5) Any component at any level is ready to replay hot-render at any point in time.
After this process React-Hot-Loader know how to update the actual code, and already did it during the render. This step could lead to 2-3 render of all components affected by the update - hot-render, normal-render, re-render caused by .forceUpdate, depending on when RHL detects update (before render, or during the render).
In case hot-render failed to reconcile the tree - it will report about it. Use logLevel: 'debug'
to get these messages.
Note! In order to be able render react-tree we have to convert all SFC into Statefull classes. Otherwise, we could not provide a correct
context
used by the previous render.
When React going to create an element A, React-Hot-Loader replaces that element by A1 - a small class, inherited from the original component.
When React-Hot-Loader understood that Component A1 should be replaced by Component A2 it
- replaces the prototype of A1(it was A), by the A2.
- copy over all the keys from A2 prototype to the top level prototype, replacing the function code by call-thought wrapper.
- replaces also all the prototypes in prototype chain, as long they also should be replaced, and someone (babel helpers) may check the old and the new code using
instanceOf
operator. This operation destroys the old classes. - copies over all static props and descriptors.
** by this point A1 become A2, except the constructor. There is no way to replace contructor **
- creates an instance of A1 and A2, using some
props+context
from the instances of A1, created before. - compares the a1(the current), a2(the new), and a0(the initial), in search of changes made in a constructor - anther values, bound or arrow functions and so on.
- stored all the changes in a special variable. Ie all the changes for the new components, to make a2 from a0(constructor is unchanged), and
level up
a1 instances to a2. - on component render or initition apply all the changes using eval, to execute the code in the correct scope and context.