Optimize dev mode compile (#1348)
This commit is contained in:
parent
c589af84c1
commit
7397cd795a
@ -18,6 +18,7 @@ from typing import (
|
||||
|
||||
from fastapi import FastAPI, UploadFile
|
||||
from fastapi.middleware import cors
|
||||
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
|
||||
from socketio import ASGIApp, AsyncNamespace, AsyncServer
|
||||
from starlette_admin.contrib.sqla.admin import Admin
|
||||
from starlette_admin.contrib.sqla.view import ModelView
|
||||
@ -437,6 +438,14 @@ class App(Base):
|
||||
|
||||
def compile(self):
|
||||
"""Compile the app and output it to the pages folder."""
|
||||
# Create a progress bar.
|
||||
progress = Progress(
|
||||
*Progress.get_default_columns()[:-1],
|
||||
MofNCompleteColumn(),
|
||||
TimeElapsedColumn(),
|
||||
)
|
||||
task = progress.add_task("Compiling: ", total=len(self.pages))
|
||||
|
||||
for render, kwargs in DECORATED_ROUTES:
|
||||
self.add_page(render, **kwargs)
|
||||
|
||||
@ -450,47 +459,60 @@ class App(Base):
|
||||
# Empty the .web pages directory
|
||||
compiler.purge_web_pages_dir()
|
||||
|
||||
# Compile the root document with base styles and fonts.
|
||||
compiler.compile_document_root(self.stylesheets)
|
||||
# Store the compile results.
|
||||
compile_results = []
|
||||
|
||||
# Compile the theme.
|
||||
compiler.compile_theme(self.style)
|
||||
|
||||
# Compile the Tailwind config.
|
||||
compiler.compile_tailwind(
|
||||
dict(**config.tailwind, content=constants.TAILWIND_CONTENT)
|
||||
if config.tailwind is not None
|
||||
else {}
|
||||
)
|
||||
|
||||
# Compile the pages.
|
||||
# Compile the pages in parallel.
|
||||
custom_components = set()
|
||||
thread_pool = ThreadPool()
|
||||
compile_results = []
|
||||
for route, component in self.pages.items():
|
||||
component.add_style(self.style)
|
||||
compile_results.append(
|
||||
thread_pool.apply_async(
|
||||
compiler.compile_page,
|
||||
args=(
|
||||
route,
|
||||
component,
|
||||
self.state,
|
||||
self.connect_error_component,
|
||||
),
|
||||
with progress:
|
||||
for route, component in self.pages.items():
|
||||
progress.advance(task)
|
||||
component.add_style(self.style)
|
||||
compile_results.append(
|
||||
thread_pool.apply_async(
|
||||
compiler.compile_page,
|
||||
args=(
|
||||
route,
|
||||
component,
|
||||
self.state,
|
||||
self.connect_error_component,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
# Add the custom components from the page to the set.
|
||||
custom_components |= component.get_custom_components()
|
||||
# Add the custom components from the page to the set.
|
||||
custom_components |= component.get_custom_components()
|
||||
thread_pool.close()
|
||||
thread_pool.join()
|
||||
|
||||
# check the results of all the threads in case an exception was raised.
|
||||
for r in compile_results:
|
||||
r.get()
|
||||
# Get the results.
|
||||
compile_results = [result.get() for result in compile_results]
|
||||
|
||||
# Compile the custom components.
|
||||
compiler.compile_components(custom_components)
|
||||
compile_results.append(compiler.compile_components(custom_components))
|
||||
|
||||
# Compile the root document with base styles and fonts.
|
||||
compile_results.append(compiler.compile_document_root(self.stylesheets))
|
||||
|
||||
# Compile the theme.
|
||||
compile_results.append(compiler.compile_theme(self.style))
|
||||
|
||||
# Compile the Tailwind config.
|
||||
compile_results.append(
|
||||
compiler.compile_tailwind(
|
||||
dict(**config.tailwind, content=constants.TAILWIND_CONTENT)
|
||||
if config.tailwind is not None
|
||||
else {}
|
||||
)
|
||||
)
|
||||
|
||||
# Write the pages at the end to trigger the NextJS hot reload only once.
|
||||
thread_pool = ThreadPool()
|
||||
for output_path, code in compile_results:
|
||||
compiler_utils.write_page(output_path, code)
|
||||
thread_pool.apply_async(compiler_utils.write_page, args=(output_path, code))
|
||||
thread_pool.close()
|
||||
thread_pool.join()
|
||||
|
||||
|
||||
async def process(
|
||||
|
@ -1,14 +1,12 @@
|
||||
"""Compiler for the reflex apps."""
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import wraps
|
||||
from typing import Callable, List, Set, Tuple, Type
|
||||
from typing import List, Set, Tuple, Type
|
||||
|
||||
from reflex import constants
|
||||
from reflex.compiler import templates, utils
|
||||
from reflex.components.component import Component, CustomComponent
|
||||
from reflex.components.component import Component, ComponentStyle, CustomComponent
|
||||
from reflex.state import State
|
||||
from reflex.style import Style
|
||||
from reflex.utils import imports
|
||||
from reflex.vars import ImportVar
|
||||
|
||||
@ -144,36 +142,6 @@ def _compile_tailwind(
|
||||
)
|
||||
|
||||
|
||||
def write_output(fn: Callable[..., Tuple[str, str]]):
|
||||
"""Write the output of the function to a file.
|
||||
|
||||
Args:
|
||||
fn: The function to decorate.
|
||||
|
||||
Returns:
|
||||
The decorated function.
|
||||
"""
|
||||
|
||||
@wraps(fn)
|
||||
def wrapper(*args, write: bool = True) -> Tuple[str, str]:
|
||||
"""Write the output of the function to a file.
|
||||
|
||||
Args:
|
||||
*args: The arguments to pass to the function.
|
||||
write: Whether to write the output to a file.
|
||||
|
||||
Returns:
|
||||
The path and code of the output.
|
||||
"""
|
||||
path, code = fn(*args)
|
||||
if write:
|
||||
utils.write_page(path, code)
|
||||
return path, code
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@write_output
|
||||
def compile_document_root(stylesheets: List[str]) -> Tuple[str, str]:
|
||||
"""Compile the document root.
|
||||
|
||||
@ -194,8 +162,7 @@ def compile_document_root(stylesheets: List[str]) -> Tuple[str, str]:
|
||||
return output_path, code
|
||||
|
||||
|
||||
@write_output
|
||||
def compile_theme(style: Style) -> Tuple[str, str]:
|
||||
def compile_theme(style: ComponentStyle) -> Tuple[str, str]:
|
||||
"""Compile the theme.
|
||||
|
||||
Args:
|
||||
@ -214,7 +181,6 @@ def compile_theme(style: Style) -> Tuple[str, str]:
|
||||
return output_path, code
|
||||
|
||||
|
||||
@write_output
|
||||
def compile_page(
|
||||
path: str,
|
||||
component: Component,
|
||||
@ -240,7 +206,6 @@ def compile_page(
|
||||
return output_path, code
|
||||
|
||||
|
||||
@write_output
|
||||
def compile_components(components: Set[CustomComponent]):
|
||||
"""Compile the custom components.
|
||||
|
||||
@ -258,7 +223,6 @@ def compile_components(components: Set[CustomComponent]):
|
||||
return output_path, code
|
||||
|
||||
|
||||
@write_output
|
||||
def compile_tailwind(
|
||||
config: dict,
|
||||
):
|
||||
|
@ -18,7 +18,7 @@ from reflex.components.base import (
|
||||
Script,
|
||||
Title,
|
||||
)
|
||||
from reflex.components.component import Component, CustomComponent
|
||||
from reflex.components.component import Component, ComponentStyle, CustomComponent
|
||||
from reflex.event import get_hydrate_event
|
||||
from reflex.state import State
|
||||
from reflex.style import Style
|
||||
@ -188,7 +188,7 @@ def create_document_root(stylesheets: List[str]) -> Component:
|
||||
)
|
||||
|
||||
|
||||
def create_theme(style: Style) -> Dict:
|
||||
def create_theme(style: ComponentStyle) -> Dict:
|
||||
"""Create the base style for the app.
|
||||
|
||||
Args:
|
||||
|
@ -190,7 +190,7 @@ CONFIG_FILE = f"{CONFIG_MODULE}{PY_EXT}"
|
||||
# The previous config file.
|
||||
OLD_CONFIG_FILE = f"pcconfig{PY_EXT}"
|
||||
# The deployment URL.
|
||||
PRODUCTION_BACKEND_URL = "https://{username}-{app_name}.api.reflex.app"
|
||||
PRODUCTION_BACKEND_URL = "https://{username}-{app_name}.api.pynecone.app"
|
||||
# Token expiration time in seconds.
|
||||
TOKEN_EXPIRATION = 60 * 60
|
||||
|
||||
|
@ -178,8 +178,7 @@ def deploy(dry_run: bool = typer.Option(False, help="Whether to run a dry run.")
|
||||
|
||||
# Compile the app in production mode.
|
||||
typer.echo("Compiling production app")
|
||||
app = prerequisites.get_app().app
|
||||
build.export_app(app, zip=True, deploy_url=config.deploy_url)
|
||||
export(for_reflex_deploy=True)
|
||||
|
||||
# Exit early if this is a dry run.
|
||||
if dry_run:
|
||||
|
@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from rich import print
|
||||
@ -42,22 +41,12 @@ def run_process_and_launch_url(
|
||||
cwd=constants.WEB_DIR,
|
||||
)
|
||||
|
||||
current_time = datetime.now()
|
||||
if process.stdout:
|
||||
for line in process.stdout:
|
||||
if "ready started server on" in line:
|
||||
url = line.split("url: ")[-1].strip()
|
||||
print(f"App running at: [bold green]{url}")
|
||||
if (
|
||||
"Fast Refresh" in line
|
||||
or "compiling..." in line
|
||||
and (datetime.now() - current_time).total_seconds() > 1
|
||||
):
|
||||
current_time = datetime.now()
|
||||
print(
|
||||
f"[yellow][Updating App][/yellow] Applying changes and refreshing. Time: {current_time}"
|
||||
)
|
||||
elif loglevel == constants.LogLevel.DEBUG:
|
||||
if loglevel == constants.LogLevel.DEBUG:
|
||||
print(line, end="")
|
||||
|
||||
|
||||
@ -130,8 +119,8 @@ def run_backend(
|
||||
"--log-level",
|
||||
loglevel,
|
||||
"--reload",
|
||||
"--reload-exclude",
|
||||
f"'{constants.WEB_DIR}/*'",
|
||||
"--reload-dir",
|
||||
app_name.split(".")[0],
|
||||
]
|
||||
process = subprocess.Popen(cmd)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user