Summary:
The `Systrace` and `Refresh` dependencies are injected into the `metroRequire` implementation by assigning the values to e.g. `require.Systrace = ...`.
The issue with this approach is that some `require` implementations might not support extending the `require` object or doing so results in a degraded performance. An example where this is the case is Hermes where changing the `require` object forces Hermes to opt out of the static require optimization.
This diff extends Metro so that the `Systrace` and `Refresh` implementation can either be injected by assigning to `require.Systrace` or by exposing the implementation in the global scope. It further changes the `Systrace` and `Refresh` modules to inject the instances using the global scope instead of extending `require`.
Changelog:
[Internal][Changed] - Expose Systrace and ReactRefresh as globals instead of extending require.
Reviewed By: motiz88
Differential Revision: D25693381
fbshipit-source-id: 254d66d43e7a56d3310cf1a17d5146b8d1307562
Summary: Report fast refreshes to the native module that handles reporting
Reviewed By: cpojer
Differential Revision: D17528523
fbshipit-source-id: 6f8a0b72a18c2d08ab160dc8b6621fce5420a473
Summary: This diff adds reload reasons to Fast Refresh. This will help us understand why, for internal Facebook users, Fast Refresh is bailing out to a full reload so that we can improve it for everyone.
Reviewed By: cpojer
Differential Revision: D17499348
fbshipit-source-id: b6e73dc3f396c8531a0872f5572a13928450bb3b
Summary:
This updates `react-refresh` to 0.3.0 which brings a new feature: we can now detect if the root fails on _the initial mount_. In that case we currently can't recover with Fast Refresh because we don't know which element to retry mounting. (In the future, we can lift this limitation, but it would require more changes in React renderer.)
Before this diff, after you fix an error on initial mount, you would see a blank screen (because nothing managed to mount).
After this diff, after you fix an error on initial mount, you would fall back to a full reload.
This diff doesn't affect errors on updates. We can recover from those, just like before.
Reviewed By: cpojer
Differential Revision: D16440836
fbshipit-source-id: 4a414202a9eab894acd7baa0525c25ff003dd323
Summary: I originally added `forceFullRefresh` as an escape hatch in case Fast Refresh is too unreliable. In practice we haven't seen any major issues with it. Since this option is already very obscure, I'm just removing it.
Reviewed By: shergin
Differential Revision: D16286632
fbshipit-source-id: c3dc44cffd459912e194e273acf868f3380c64cc
Summary:
This is a revamp of how we decide whether to stop at a refresh boundary or to bubble to the next one.
We used to decide that at module initialization. However, that's both unnecessary overhead on start (for modules you don't plan to edit), and is actually insufficient.
In particular, even if a module only exports components (and thus is a Refresh Boundary), consecutive versions of that module might not be compatible.
For example, any of these changes should trigger reevaluation of parents:
- Adding or removing exports
- Renaming the exported component (which probably means you exported a different one, and we shouldn't preserve state)
- Converting from a class to a function, or back
- Wrapping something in a HOC
The new system handles these cases by comparing the Refresh "families" corresponding to exports, and bubbling the update up if some of them don't match up.
The tests have been rewritten from the webpack-inspired `module.hot` API (which we no longer use directly) to the Refresh API.
Reviewed By: rubennorte
Differential Revision: D16036044
fbshipit-source-id: 18018548d4aaa05877ae6fbaffe40c993c77cdf0
Summary:
Since we always create `module.hot` objects, the `module.hot` checks were unnecessary. They give a false impression that we're checking for a Hot Reloading mode. However, they're just Flow refinements and always exist in DEV. I made that explicit by throwing early.
Similarly, I removed a `module.hot` check inside `setupReactRefresh`, as it is always truish in DEV.
Finally, I'm adding a new mechanism as an escape hatch. It lets you do:
```
if (__DEV__) {
require.Refresh.forceFullRefresh = true;
}
```
in your entry point and opt into full refreshes on every edit. This sounds similar to "Reload-on-Save". That is because in the next diff, I plan to remove "Reload-on-Save" from user-visible options (but it'll stay for automated workflows).
So this workaround is intended for people who for one reason or another don't want to opt into Hot Reloading as an alternative. We'll need to talk to them and find out why.
Reviewed By: rickhanlonii
Differential Revision: D15958475
fbshipit-source-id: 674187ddf86a4e286dfae28f4182555a8b5d7396
Summary:
This removes React Transform HMR in favor of the new React Refresh implementation. It should only affect the "Enable Hot Reloading" mode. In further diffs I will remove "React Transform HMR" completely.
This is technically a breaking change for Metro so it'll need a version bump.
Reviewed By: rickhanlonii, rubennorte
Differential Revision: D15903585
fbshipit-source-id: 074380b00868cb31857f599a03799d3584c35d87