Repository navigation
Move the pre-paint scripts out of <head> so cold loads stop failing to hydrate - #43
Conversation
…o hydrate On a cold cache, React still gave up hydrating the root now and then (minified error #418): 2 of 120 cold loads on production. #36 made the consequence harmless by restoring the settings from storage, but left the trigger: the two hand-written pre-paint scripts in <head>, which React matches node by node while the webpack runtime removes the chunk <script> tags it has finished loading from the same <head>. The scripts now sit at the top of <body>, as in AlgoAlgo, where the same move took cold-load failures from 5 of 120 to 0 of 240 on production. They still run before the first paint, because they are the first thing the parser meets in <body>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Measured on production after the merge (deployment of a073eb5): the same 240 cold-cache loads in headless Chrome at 1440×900, rotating through
At the old rate of 2 in 120, 240 clean loads in a row would happen with probability about 0.018. Together with AlgoAlgo, where the same move took the rate from 5 of 120 to 0 of 240, this confirms the scripts in |
Summary
Follow-up to #36, whose PR left the trigger of React error #418 unlocated.
On a cold cache, React still gives up hydrating the root now and then and renders it again on the client. Measured on production before this change: 120 cold-cache loads in headless Chrome at 1440×900, rotating through
/,/array,/stack,/hash,/heapand/atlas, withdd-lang = zhanddd-theme = lightstored before any script ran. Error #418 appeared 2 times (on/heapand/atlas). Thanks to #36 no setting was lost in either case, but the whole root was still rendered again.The trigger. The two hand-written pre-paint scripts sat in
<head>. React matches those nodes one by one during hydration, while the webpack runtime removes the chunk<script>tags it has finished loading from the same<head>. When a removal lands in the middle of that matching, hydration fails.The change. The scripts now sit at the top of
<body>. They still run before the first paint, because they are the first thing the parser meets in<body>. The settings restore from #36 stays as a safety net. A comment intheme-provider.tsxthat said the script is in<head>is updated.AlgoAlgo has the same shell and the same failure, and the same move fixed it there (renrenmimi/AlgoAlgo#15). Before it, 5 of 120 cold loads failed on production; after it, 0 of 240.
Test plan
npx tsc --noEmit,npm test(104 passed),npm run build.🤖 Generated with Claude Code