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

Hot loading support #40

Merged
merged 11 commits into from
Mar 4, 2018
Merged

Conversation

ekhaled
Copy link
Contributor

@ekhaled ekhaled commented Jan 10, 2018

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 and destroy, 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:

{
  rollback: <Component>,
  component: <Component>,
  instances: [<Array>]
}

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 as state, options, target etc.
Destroys the proxied component.
Calls the _register method to resolve newest version of component.
_mounts 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 missing import), it's caught, logged in the console, and then an attempt is made to instantiate the component stored in rollback.

@ekhaled
Copy link
Contributor Author

ekhaled commented Jan 11, 2018

cc @Rich-Harris

@Rich-Harris Rich-Harris merged commit e5d8517 into sveltejs:master Mar 4, 2018
@Rich-Harris
Copy link
Member

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.

@ekhaled
Copy link
Contributor Author

ekhaled commented Mar 4, 2018

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.

@ekhaled ekhaled deleted the hot-loading-support branch March 4, 2018 15:08
@Rich-Harris
Copy link
Member

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.

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.

2 participants