feat: add hydrate_fallback API for the page hydration window#6630
feat: add hydrate_fallback API for the page hydration window#6630adhami3310 wants to merge 3 commits into
Conversation
Render a component during the React Router hydration window instead of a blank white page. - rx.App(hydrate_fallback=...): a Component/ComponentCallable compiled to React Router's HydrateFallback export in root.jsx (inside the document Layout, so it gets theme/color-mode context). - Config.hydrate_fallback (env: REFLEX_HYDRATE_FALLBACK): dotted import path to a no-arg callable returning a component, used when App.hydrate_fallback is unset. App field takes precedence. Factor the import-path resolution shared with extra_overlay_function into _resolve_import_path / _component_from_import_path, switching from __import__ to importlib.import_module so nested module paths resolve correctly. Closes ENG-9724
Merging this PR will not alter performance
Comparing Footnotes
|
Greptile SummaryThis PR introduces
Confidence Score: 5/5Safe to merge. The change is additive: no existing compilation paths are altered unless a hydrate_fallback is explicitly configured. All changed code paths are additive β hydrate_fallback defaults to None at every layer, so builds without a fallback produce identical output to before. The importlib refactor of extra_overlay_function is a transparent correctness fix with a corrected integration test. The new helpers are well-tested with success, error, and edge-case coverage. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "fix: clearer error for single-segment hy..." | Re-trigger Greptile |
Guard _resolve_import_path against paths with no dot (module would be empty, yielding an opaque 'Empty module name' error). Document the deliberate fail-fast vs graceful-degradation split between the App-field and config resolution paths. Addresses review feedback on #6630.
What
Adds an API to render a component during the React Router hydration window instead of a blank white page.
rx.App(hydrate_fallback=...)β aComponent | ComponentCallablecompiled to React Router'sHydrateFallbackexport inroot.jsx. Rendered inside the documentLayout, so it inherits theme/color-mode context.Config.hydrate_fallback(settable via theREFLEX_HYDRATE_FALLBACKenv var) β a dotted import path to a no-arg callable returning a component, used whenApp.hydrate_fallbackis not set. Same resolution pattern asextra_overlay_function.App.hydrate_fallbackwins over thehydrate_fallbackconfig.Scope / limitations
HydrateFallbackonly covers the hydration window β after the JS bundle loads and React mounts, until hydration/route loaders finish. It does not cover the pre-JS bundle-download window.index.html, so it shows immediately; in dev it appears once the dev bundle mounts.Implementation
reflex/app.py:App.hydrate_fallbackfield;_resolve_hydrate_fallback()(App field β config import path); shared_resolve_import_path/_component_from_import_pathhelpers βextra_overlay_functionnow uses the latter too, switched from__import__toimportlib.import_moduleso nested module paths resolve correctly (the integration test's import path was corrected accordingly).packages/reflex-base/.../config.py:Config.hydrate_fallbackfield.app_root_templateemits theHydrateFallbackexport; threaded through_compile_app/compile_app_root/compile_app.Tests
Codegen (emit/omit), config + env path, App-over-config precedence, and the resolver helpers. Full unit suite passes (77.25% coverage); ruff + pyright clean.
Closes ENG-9724