From da56f1cd3ff5047bfb7f5c5825935eb807069295 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 8 Aug 2025 19:22:58 -0700 Subject: [PATCH 1/2] fix various issues with frontend_path --- .../.templates/jinja/web/vite.config.js.jinja2 | 2 +- reflex/.templates/web/utils/state.js | 12 +----------- reflex/app.py | 2 +- reflex/route.py | 4 ++++ reflex/state.py | 2 +- reflex/utils/build.py | 16 +++++++++++++++- reflex/utils/prerequisites.py | 5 ++++- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/reflex/.templates/jinja/web/vite.config.js.jinja2 b/reflex/.templates/jinja/web/vite.config.js.jinja2 index 95872ab2ccb..66db5119e91 100644 --- a/reflex/.templates/jinja/web/vite.config.js.jinja2 +++ b/reflex/.templates/jinja/web/vite.config.js.jinja2 @@ -25,13 +25,13 @@ function alwaysUseReactDomServerNode() { } export default defineConfig((config) => ({ - base: "{{base}}", plugins: [ alwaysUseReactDomServerNode(), reactRouter(), safariCacheBustPlugin(), ], build: { + assetsDir: "{{base}}assets".slice(1), rollupOptions: { jsx: {}, output: { diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index 9a317cf9ef4..38d33773291 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -969,17 +969,7 @@ export const useEventLoop = ( useEffect(() => { if (!sentHydrate.current) { queueEvents( - initial_events().map((e) => ({ - ...e, - router_data: { - pathname: location.pathname, - query: { - ...Object.fromEntries(searchParams.entries()), - ...params.current, - }, - asPath: location.pathname + location.search, - }, - })), + initial_events(), socket, true, navigate, diff --git a/reflex/app.py b/reflex/app.py index 6d84e6793d6..402de0ed213 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -866,7 +866,7 @@ def router(self) -> Callable[[str], str | None]: """ from reflex.route import get_router - return get_router(list(self._unevaluated_pages)) + return get_router(list(dict.fromkeys([*self._unevaluated_pages, *self._pages]))) def get_load_events(self, path: str) -> list[IndividualEventType[()]]: """Get the load events for a route. diff --git a/reflex/route.py b/reflex/route.py index 44252f63502..761ec8f974d 100644 --- a/reflex/route.py +++ b/reflex/route.py @@ -6,6 +6,7 @@ from collections.abc import Callable from reflex import constants +from reflex.config import get_config def verify_route_validity(route: str) -> None: @@ -211,6 +212,9 @@ def get_route(path: str) -> str | None: Returns: The first matching route, or None if no match is found. """ + config = get_config() + if config.frontend_path: + path = path.removeprefix(config.frontend_path) path = "/" + path.removeprefix("/").removesuffix("/") if path == "/index": path = "/" diff --git a/reflex/state.py b/reflex/state.py index 639fb3dbbef..4240ee010c2 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -2491,7 +2491,7 @@ def on_load_internal(self) -> list[Event | EventSpec | event.EventCallback] | No # Cache the app reference for subsequent calls. if type(self)._app_ref is None: type(self)._app_ref = app - load_events = app.get_load_events(self.router._page.path) + load_events = app.get_load_events(self.router.url.path) if not load_events: self.is_hydrated = True return None # Fast path for navigation with no on_load events defined. diff --git a/reflex/utils/build.py b/reflex/utils/build.py index c6ce46f50fa..d6dbd3edd33 100644 --- a/reflex/utils/build.py +++ b/reflex/utils/build.py @@ -4,11 +4,12 @@ import os import zipfile -from pathlib import Path +from pathlib import Path, PosixPath from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn from reflex import constants +from reflex.config import get_config from reflex.utils import console, path_ops, prerequisites, processes from reflex.utils.exec import is_in_app_harness @@ -201,6 +202,19 @@ def build(): processes.show_progress("Creating Production Build", process, checkpoints) _duplicate_index_html_to_parent_dir(wdir / constants.Dirs.STATIC) + config = get_config() + + if frontend_path := config.frontend_path.strip("/"): + frontend_path = PosixPath(frontend_path) + first_part = frontend_path.parts[0] + for child in list((wdir / constants.Dirs.STATIC).iterdir()): + if child.is_dir() and child.name == first_part: + continue + path_ops.mv( + child, + wdir / constants.Dirs.STATIC / frontend_path / child.name, + ) + def setup_frontend( root: Path, diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 80b309b0593..7ec082ed39c 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -1090,8 +1090,11 @@ def update_react_router_config(prerender_routes: bool = False): def _update_react_router_config(config: Config, prerender_routes: bool = False): + basename = "/" + (config.frontend_path or "").strip("/") + if not basename.endswith("/"): + basename += "/" react_router_config = { - "basename": "/" + (config.frontend_path or "").removeprefix("/"), + "basename": basename, "future": { "unstable_optimizeDeps": True, }, From 9bceafb50b4962a61d27c5cbf68b1718c9e3f094 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 8 Aug 2025 19:34:25 -0700 Subject: [PATCH 2/2] fix tests --- tests/units/test_app.py | 7 ++++++- tests/units/test_prerequisites.py | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/units/test_app.py b/tests/units/test_app.py index 7f955adb926..64fd149b123 100644 --- a/tests/units/test_app.py +++ b/tests/units/test_app.py @@ -1061,7 +1061,12 @@ def _event(name, val, **kwargs): token=kwargs.pop("token", token), name=name, router_data=kwargs.pop( - "router_data", {"pathname": "/" + route, "query": {arg_name: val}} + "router_data", + { + "pathname": "/" + route, + "query": {arg_name: val}, + "asPath": "/test/something", + }, ), payload=kwargs.pop("payload", {}), **kwargs, diff --git a/tests/units/test_prerequisites.py b/tests/units/test_prerequisites.py index 8c861e7ae77..81a717f19c0 100644 --- a/tests/units/test_prerequisites.py +++ b/tests/units/test_prerequisites.py @@ -44,7 +44,7 @@ frontend_path="/test", ), False, - 'export default {"basename": "/test", "future": {"unstable_optimizeDeps": true}, "ssr": false};', + 'export default {"basename": "/test/", "future": {"unstable_optimizeDeps": true}, "ssr": false};', ), ( Config( @@ -68,21 +68,21 @@ def test_update_react_router_config(config, export, expected_output): app_name="test", frontend_path="", ), - 'base: "/",', + 'assetsDir: "/assets".slice(1),', ), ( Config( app_name="test", frontend_path="/test", ), - 'base: "/test/",', + 'assetsDir: "/test/assets".slice(1),', ), ( Config( app_name="test", frontend_path="/test/", ), - 'base: "/test/",', + 'assetsDir: "/test/assets".slice(1),', ), ], )