-
Notifications
You must be signed in to change notification settings - Fork 72
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
Hot loading support #40
Conversation
cc @Rich-Harris |
So sorry for the extended delay getting round to this. It is some next-level mad science shit and I absolutely love it. Massive respect, thank you so much! Released 2.4.0. |
Now, now... if it could generate components by reading your mind... THAT would be mad science 😜 Joking aside, thank you very much for merging this. I just want to quickly bring your attention to this. As you can see, although methods are forwarded from the proxies perfectly, properties are kind of tightly-coupled. So, if you add properties to svelte components that might be used publicly, or by other components, give me a nudge. Slight O/T, are there plans of hot loading support on rollup? Right now, my projects have a webpack config for dev and a rollup config for build (cos, you know, smaller bundles). Would love it if I could do it all with just rollup. |
Noted, thanks. Would definitely like to have HMR in Rollup. I haven't spent any time looking how it would work; my assumption is that it'd be a little harder because modules are always concatenated. But then there's https://github.com/porsager/wright, so maybe it is possible. Something to investigate once Sapper supports Rollup, at least. |
IMHO Hot loading should be baked in here rather than relying on a separate plugin as per svelte-hot-loader
This PR is feature complete, including tests and doc updates, and is ready for review.
Below is a brief overview of how it all works.
Proxy
It works by using a proxy class to wrap the actual component. Once wrapped, for all intents and purposes, the proxy masquerades as the component.
It forwards all method calls (including custom methods) to the wrapped component and references all relevant component properties.
For some methods, such as
constructor
,_mount
,_unmount
anddestroy
, the proxy does some additional book-keeping before forwarding the method calls.The proxy then adds a couple of extra methods,
_register
and_rerender
(which I'll explain later).Registry
There is a global Registry that holds references to un-proxied original components (before they get proxied). It also holds references to all rendered instances of a particular component.
There is also a
rollback
key that helps in rolling back in case there is an error with a component after hot reload.The signature of a registry item looks like this:
Combination of Proxy and Registry
When a component (remember the component is actually the proxy now) is instantiated. It uses the
_register
method to resolve the actual component from the Registry, instantiates it, and then starts proxying its methods and properties.It also registers it's current instance in the Registry;
When the same component gets hot reloaded... First the
rollback
property in the Registry is updated with the last version of the component.Then the Registry is updated with the new version of the component.
Then we go through all the instances in the Registry and call the
_rerender
method on them.On
_rerender
the proxy stores all props that need to carry over, such asstate
,options
,target
etc.Destroys the proxied component.
Calls the
_register
method to resolve newest version of component._mount
s the component in the same place if it was already mounted.Finally, it restores the
state
from the old version of the component.If there is an error during
_register
(e.g: a missingimport
), it's caught, logged in the console, and then an attempt is made to instantiate the component stored inrollback
.