Repository navigation
Render state contexts without a component per substate on the server - #7369
Conversation
The server renders the page once and never applies a delta, so the per-substate SubstateProvider (#6181) only adds a render level per substate there. The server renderer recurses once per level, and with ~150 substates a cold render used nearly the whole Node stack, intermittently failing every route with a non-RangeError overflow that React cannot recover from. On the server, StateProvider now provides the initial state through bare context providers; the browser keeps one SubstateProvider per substate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQ4shGzkLwvScpUv6vxqHm
|
There was a problem hiding this comment.
No issues found across 4 files
You’re at about 92% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQ4shGzkLwvScpUv6vxqHm
Merging this PR will degrade performance by 4.21%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | test_var_access[non_mutable_scalar] |
33.1 ms | 34.6 ms | -4.21% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing fix/server-state-provider-depth (a419581) with main (02efed7)
Footnotes
-
17 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
The existing test only checks the generated text. This one imports the generated context module in node, with the modules it imports stubbed, and walks the tree StateProvider returns on the server for 200 substates: one context per substate, each with its initial state, and no component or hook between them. It fails against the template before the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQ4shGzkLwvScpUv6vxqHm
|
CodSpeed Performance Analysis reports a 4.2% regression in
I tried to re-run the benchmark workflow (run 36791240447) to confirm, but I don't have permission (403). A maintainer can re-run it, or acknowledge the result in CodSpeed. Generated by Claude Code |
All Submissions:
Type of change
Changes To Core Features:
What and why
#6181 gave every substate its own
SubstateProviderso a delta re-renders only the contexts it changes. On the server that component has no job (the page renders once and no delta is ever applied), but it adds a second render level per substate. React's server renderer recurses once per level, so the depth of every page render doubled.In an app with ~150 substates this intermittently failed every route in the dev server with a 500 (
Unexpected Server Error/SyntaxError: Invalid regular expression: /[^a-z-]/: Stack overflow) that cleared on its own after 40–60 s. Measured on that app:csselement 1,254 frames deep with about 7 KB of the default ~984 KB stack left.Maximum call stack size exceeded: it re-renders that subtree from a fresh stack. An overflow that surfaces as anything else is not recovered, and the request fails. The regexSyntaxErrorabove is one example; aTypeErrorreading$$typeofon auseContextis another.--stack-size=971and960) reproduced the 500s reliably, including the fail-then-recover pattern.Change
context_templatenow emits the substates once as aSUBSTATEStable, plus two providers chosen at module load:ClientStateProvider(browser): unchanged behaviour.DispatchProviderand oneSubstateProviderper substate, memoized onchildren, built with a loop instead of a generated nested expression.ServerStateProvider(typeof document === "undefined", the same testuseIsomorphicLayoutEffectuses): bare context providers carryinginitialState, one level per substate. No reducers or dispatch registry, because nothing dispatches on the server.Hydration is unaffected: wrapper components produce no DOM and do not fork the tree. In the app above there were no hydration warnings on any page, with the same console output as before the change.
Same app, with the fix:
csselement--stack-size950–990 KB and 960/971--stack-sizedown to 500 KBTests
test_context_template_server_state_provider_is_flat(new) and the updatedtest_context_template_one_provider_per_substatefail onmainand pass here.test_context_js_template.pylocatedEventLoopProviderby the oldexport function StateProvidertext; it now anchors on the next declaration.tests/units/compiler: 308 passed. The full unit suite has the same failures with and without this change (227reflex_clitests that fail in my environment on cleanmaintoo).tests/integration/tests_playwright/test_router_query.py: 8 passed in dev and prod, including Create separate context providing components for each state #6181's case where one delta updates two sibling substates.🤖 Generated with Claude Code
https://claude.ai/code/session_01CQ4shGzkLwvScpUv6vxqHm
Generated by Claude Code