Fast refresh

Summary:
This diff enables optional [Fast Refresh](https://reactnative.dev/docs/fast-refresh) for Flipper in dev mode. It can be opted-in using additional argument "--fast-refresh": `yarn start --fast-refresh`. I've copy-pasted the most part of implementation from React Native with some minor changes.

I made this optional for now as it works not ideally. In most cases which I checked it works fine, however for some files it falls back to full refresh (e.g. when `desktop/plugins/network/index.tsx` changed) and sometimes doesn't refresh content even after change detected and re-compiled (e.g. when `src/ui/components/searchable/Searchable.tsx` is changed, Network plugin which is dependent on it is not refreshed automatically).

State from redux is restored after fast refresh, but local state in class-based components is cleared. For function-based components local state is also stored, so it's an additional point to make plugins components functional :)

Also, for now there is no UI for Fast Refresh (loading indicator etc), information is just logged to console.

Changelog: Experimental support for Fast Refresh in dev mode can be enabled by `yarn start --fast-refresh`.

Reviewed By: jknoxville

Differential Revision: D20993073

fbshipit-source-id: 65632788df105a85fac0b924b7808120900b349e
This commit is contained in:
Anton Nikolaev
2020-04-14 07:10:38 -07:00
committed by Facebook GitHub Bot
parent f506d0eb61
commit a54aad57a7
7 changed files with 419 additions and 36 deletions

View File

@@ -0,0 +1,52 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {default as HmrClient} from './HMRClient';
import {default as ReactRefreshRuntime} from 'react-refresh/runtime';
HmrClient.setup(
'web',
'/src/init-fast-refresh.bundle',
'localhost',
'3000',
true,
);
ReactRefreshRuntime.injectIntoGlobalHook(window);
const Refresh = {
performFullRefresh(reason) {
console.log('Perform full refresh', reason);
window.location.reload();
},
createSignatureFunctionForTransform:
ReactRefreshRuntime.createSignatureFunctionForTransform,
isLikelyComponentType: ReactRefreshRuntime.isLikelyComponentType,
getFamilyByType: ReactRefreshRuntime.getFamilyByType,
register: ReactRefreshRuntime.register,
performReactRefresh() {
if (ReactRefreshRuntime.hasUnrecoverableErrors()) {
console.error('Fast refresh - Unrecolverable');
window.location.reload();
return;
}
ReactRefreshRuntime.performReactRefresh();
console.log('Perform react refresh');
},
};
require.Refresh = Refresh;
// eslint-disable-next-line import/no-commonjs
require('./init.tsx');