diff --git a/reflex/app.py b/reflex/app.py index d290b8f49..921a66f7f 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -30,6 +30,7 @@ from typing import ( Optional, Set, Type, + TypeVar, Union, get_args, get_type_hints, @@ -1077,7 +1078,7 @@ class App(MiddlewareMixin, LifespanMixin): progress.advance(task) # Store the compile results. - compile_results = [] + compile_results: list[tuple[str, str]] = [] progress.advance(task) @@ -1159,7 +1160,25 @@ class App(MiddlewareMixin, LifespanMixin): # Use a forking process pool, if possible. Much faster, especially for large sites. # Fallback to ThreadPoolExecutor as something that will always work. executor = None - if ( + if environment.REFLEX_COMPILE_USE_MAIN_THREAD.get(): + T = TypeVar("T") + + class MainThreadExecutor: + def __enter__(self): + return self + + def __exit__(self, *args): + pass + + def submit( + self, fn: Callable[..., T], *args, **kwargs + ) -> concurrent.futures.Future[T]: + future_job = concurrent.futures.Future() + future_job.set_result(fn(*args, **kwargs)) + return future_job + + executor = MainThreadExecutor() + elif ( platform.system() in ("Linux", "Darwin") and (number_of_processes := environment.REFLEX_COMPILE_PROCESSES.get()) is not None @@ -1179,9 +1198,9 @@ class App(MiddlewareMixin, LifespanMixin): ExecutorSafeFunctions.STATE = self._state with executor: - result_futures = [] + result_futures: list[concurrent.futures.Future[tuple[str, str]]] = [] - def _submit_work(fn: Callable, *args, **kwargs): + def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs): f = executor.submit(fn, *args, **kwargs) result_futures.append(f) @@ -1236,10 +1255,12 @@ class App(MiddlewareMixin, LifespanMixin): progress.advance(task) # Compile custom components. - *custom_components_result, custom_components_imports = ( - compiler.compile_components(custom_components) - ) - compile_results.append(custom_components_result) + ( + custom_components_output, + custom_components_result, + custom_components_imports, + ) = compiler.compile_components(custom_components) + compile_results.append((custom_components_output, custom_components_result)) all_imports.update(custom_components_imports) progress.advance(task) diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 7cd87fb71..577d533a0 100644 --- a/reflex/compiler/compiler.py +++ b/reflex/compiler/compiler.py @@ -508,7 +508,7 @@ def compile_tailwind( The compiled Tailwind config. """ # Get the path for the output file. - output_path = get_web_dir() / constants.Tailwind.CONFIG + output_path = str((get_web_dir() / constants.Tailwind.CONFIG).absolute()) # Compile the config. code = _compile_tailwind(config) diff --git a/reflex/config.py b/reflex/config.py index 21614b9b1..63d420c86 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -522,6 +522,9 @@ class EnvironmentVariables: Path(constants.Dirs.UPLOADED_FILES) ) + # Whether to use the main thread for compiling the frontend. Takes precedence over other compile options. + REFLEX_COMPILE_USE_MAIN_THREAD: EnvVar[bool] = env_var(False) + # Whether to use separate processes to compile the frontend and how many. If not set, defaults to thread executor. REFLEX_COMPILE_PROCESSES: EnvVar[Optional[int]] = env_var(None)