gaearon / react-hot-loader

Tweak React components in real time. (Deprecated: use Fast Refresh instead.)
http://gaearon.github.io/react-hot-loader/
MIT License
12.26k stars 801 forks source link

The end of React-Hot-Loader #1024

Open theKashey opened 6 years ago

theKashey commented 6 years ago

By this time we have reached limits of "hot replacement", and to overpass them we need something new. (Source issue : #1001)

The problem - there are so many ways to DEFINE react component, what we could not handle all of them.

The major problems today:

Just a two points, we are unable to overtake. React-Hot-Loader could handle most of the React code, and would fit for almost any project. But we are stuck.


I think React-Hot-Loader was a good spike, and it's time to more forward, and look to the way to to implement it inside React, stop hacking it, but start being a part of it:

That will solve all the issues, and super simple to implement, as long we are already having everything we need for it, in the current RHL, but in much more complex form.

Something like componentComparator we spiked for Preact integration - https://github.com/gaearon/react-hot-loader/pull/960/files#diff-b26fdb1bb246da9739b0a423fbe9a65dR6, https://github.com/developit/preact/pull/1120 - just expose RHL internals about compareAndSwap, and that's all. Probably it just a hundred lines for everything - changed properties tracking from proxies, class comparator from hotRender, and nothing more.

It should not be super complex to integrate this to React, as long there are only two location to hook into.

As result - we could drop instantly hot-renderer, and next drop componentProxy - two major pieces of RHL.

gaearon commented 6 years ago

We have some ideas but it’s too early to share yet. I think there’ll be a way forward within a year.

gaearon commented 6 years ago

By “I think” in this case I mean “I’m pretty sure”. I’m optimistic about this for the first time in a few years :-)

theKashey commented 6 years ago

Could you measure your optimism in terms of should we continue our efforts to improve the RHL way to hot-reload or it would become obsolete... more sooner than later?

In my current vision - RHL is a super complex thing, and we should stop moving it that direction, should stop fighting with React, and try to teamup, as we tried with Preact.

React-Hot-Loader was started as a preserver of Component's type equality, to fool reconciler from the outside. And that is something not letting us moving forward. Not "fooling reconciler", but "outside". And that is something RHL could not without your help. And that is something, that will sunset it.

gaearon commented 6 years ago

Yep, all of this sounds correct

gaearon commented 6 years ago

There are two separate parts to this problem:

The first one isn’t really a problem. It may seem like one, but it’s really the second problem that’s making the first one difficult.

The solution I’m thinking about solves the second problem, leaving RHL to only worry about the first one, and drastically limiting its complexity.

theKashey commented 6 years ago

Extracting behavior from the fresh version into the wrapper and transplanting it

This is what we are currently doing, and this is what we could not solve.

Initially we had only class.methods, and it is easy to inject a new ones into the prototype. Next - "bound" methods. Ok - just "bind" them again Next - arrow functions - cast them toString, and eval back (a did not found another solution) But when someone will create a new class member using factory function(per-instance-memoization, so popular after componentWillReceiveProps deprecation, is a good example) - there is no way to repeat it, and preserve possible used this - you have to fight with JS, you have to fight with Babel.

The easiest way - extract constructor body to another function, to be able to replay ES6 constructor for custom this. I am not sure that is the right way.

The simplest way - create a new instance how it should be, and copy some known methods from old instances. Reverse operation. And then explain React that new type is the same as an old one. It will also solve ".type !== Component".

Might be it is better to store variables we want to preserve, call extracted constructor on the current component, and restore variables back, as long that's a goal - it will keep refs, but still makes .type !== Component a thing.

The current version could solve almost any code from "last year", but as long React evolves - new coding patterns emerges, and as RHL failed to support Arrow functions in V3 - it is failing to support fabricated methods in V4. We have to found a bit more durable solution.

gaearon commented 6 years ago

Yeah, the solution I'm thinking about will eventually solve those things.

gregberge commented 6 years ago

I am happy to know that there is finally a hope for React + Hot Reloading. When I started to work on the project one year ago, I didn’t expect so much complexity. I quickly gave up but thanks to @theKashey, the project continued to live.

Today I think you should warn in readme that the latest supported version is React 16.5 and specify it in peerDependencies. And yes, stop the development 😢 even if it is your baby. Thanks again for this year of hot reloading, it would not have been possible without you!

Excited to see what @gaearon and React team are cooking 🍳😁.

theKashey commented 6 years ago

Its almost 16.6 compatible, I just need to make lazy a bit hotter. And it will be 16.7 compatible, if https://github.com/reactjs/rfcs/pull/74 would succeed. With hooks we would just be free from some issues, some side effects, and so on.

The “hot replacement” stuff should be managed by something anyway.

theKashey commented 5 years ago

Since version 4.6.0 we are "inside" React, and one may|shall use hooks - this would cure the problem.