- 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
useStatehook, also hash the source of the first argument if it exists e.g.useState(foo => true); -
For the
useReducerhook, 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();