- https://github.com/facebook/react/blob/master/packages/react-refresh/src/ReactFreshBabelPlugin.js
- https://github.com/swc-project/swc/blob/master/ecmascript/transforms/react/src/refresh/mod.rs
- facebook/react#16604 (comment)
- https://github.com/facebook/react/blob/master/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js
From reading and Dan Abramov's comment, there are really five parts.
- At the top of the file:
- Declare a
$RefreshReg$
if it doesn't exist- This really just does:
RefreshRuntime.register(ComponentIdentifier, ComponentIdentifier.name);
- This really just does:
- Run
var _s${componentIndex} = $RefreshSig$()
to generate a function for updating react refresh scoped to the component. So it's one per component.- This really just does:
RefreshRuntime.createSignatureFunctionForTransform();
- This really just does:
- Declare a
- Register all React components[2] defined in the module scope by calling the equivalent of
$RefreshReg$(ComponentIdentifier, "ComponentName")
- For each registered component:
- Call
_s()
to mark the first render of this component for"react-refresh/runtime"
. Call this at the start of the React component's function body - Track every call expression to a hook[3] inside the component, including:
- Identifier of the hook function
- Arguments passed
- For each hook's call expression, generate a signature key which is
-
The hook's identifier ref
-
The
S.Decl
(VariableDeclarator
)'s sourcevar [foo, bar] = useFooBar(); // ^--------^ This region, I think. [Judging from this line](https://github.com/facebook/react/blob/master/packages/react-refresh/src/ReactFreshBabelPlugin.js#L407)
-
For the
useState
hook, also hash the source of the first argument if it exists e.g.useState(foo => true);
-
For the
useReducer
hook, also hash the source of the second argument if it exists e.g.useReducer({}, () => ({}));
-
- If the hook component is not builtin and is defined inside a component, always reset the component state
- Call
- From the signature key generated in 3., call one of the following:
_s(ComponentIdentifier, hash(signature));
_s(ComponentIdentifier, hash(signature), true /* forceReset */);
_s(ComponentIdentifier, hash(signature), false /* forceReset */, () => [customHook1, customHook2, customHook3]);
Note: This step is only strictly required on rebuild.
if (isReactComponentBoundary(exports)) enqueueUpdateAndHandleErrors();