diff --git a/reflex/config.py b/reflex/config.py index 5f135f08e..4d26d4df4 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -201,6 +201,9 @@ class Config(Base): # The worker class used in production mode gunicorn_worker_class: str = "uvicorn.workers.UvicornH11Worker" + # npm prefer-offline flag to prefer local cache. + npm_prefer_offline: bool = False + # Attributes that were explicitly set by the user. _non_default_attributes: Set[str] = pydantic.PrivateAttr(set()) diff --git a/reflex/config.pyi b/reflex/config.pyi index 0193d6533..ccaa6381a 100644 --- a/reflex/config.pyi +++ b/reflex/config.pyi @@ -68,6 +68,7 @@ class Config(Base): rxdeploy_url: Optional[str] cp_backend_url: str cp_web_url: str + npm_prefer_offline: bool username: Optional[str] gunicorn_worker_class: str @@ -95,6 +96,7 @@ class Config(Base): rxdeploy_url: Optional[str] = None, cp_backend_url: Optional[str] = None, cp_web_url: Optional[str] = None, + npm_prefer_offline: bool=False, username: Optional[str] = None, gunicorn_worker_class: Optional[str] = None, **kwargs diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index cba05ed3d..b7927ac09 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -505,22 +505,6 @@ def install_bun(): ) -def get_packages_to_install(packages, npm_packages): # TODO: refactor - packages_to_install = [] - for _i, package in enumerate(packages): - parts = [x for x in package.split("@") if x] - if ( - len(parts) == 1 - and package not in npm_packages - or len(parts) > 1 - and parts[-1].startswith("^") - or len(parts) > 1 - and package not in npm_packages - ): - packages_to_install.append(package) - return packages_to_install - - def install_frontend_packages(packages: set[str]): """Installs the base and custom frontend packages. @@ -530,58 +514,42 @@ def install_frontend_packages(packages: set[str]): Example: >>> install_frontend_packages(["react", "react-dom"]) """ + config = get_config() package_manager = get_install_package_manager() + uses_npm = package_manager.endswith("npm") - if uses_npm: - npm_packages = processes.new_process( - [package_manager, "ls"], run=True, cwd=constants.Dirs.WEB - ).stdout.splitlines() - npm_packages = set( - [ - package.split()[1] - for package in npm_packages[1:] - if package and "empty" not in package - ] - ) + + prefer_offline = (["--prefer-offline"] if config.npm_prefer_offline and uses_npm else []) + # Install the base packages. process = processes.new_process( - [package_manager, "install", "--loglevel", "silly"], + [package_manager, "install", "--loglevel", "silly", *prefer_offline], cwd=constants.Dirs.WEB, shell=constants.IS_WINDOWS, ) processes.show_status("Installing base frontend packages", process) - config = get_config() if config.tailwind is not None: - tailwind_deps = (config.tailwind or {}).get("plugins", []) - if uses_npm: - tailwind_deps = get_packages_to_install(tailwind_deps, npm_packages) - # install tailwind and tailwind plugins as dev dependencies. - if tailwind_deps: - process = processes.new_process( - [ - package_manager, - "add", - "-d", - constants.Tailwind.VERSION, - *tailwind_deps, - ], - cwd=constants.Dirs.WEB, - shell=constants.IS_WINDOWS, - ) - processes.show_status("Installing tailwind", process) - - # Install custom packages defined in frontend_packages - if uses_npm: - packages = get_packages_to_install(packages, npm_packages) + process = processes.new_process( + [ + package_manager, + "add", + "-d", + *prefer_offline, + constants.Tailwind.VERSION, + *(config.tailwind or {}).get("plugins", []), + ], + cwd=constants.Dirs.WEB, + shell=constants.IS_WINDOWS, + ) + processes.show_status("Installing tailwind", process) if len(packages) > 0: process = processes.new_process( - [package_manager, "add", *packages], + [package_manager, "add", *packages, *prefer_offline], cwd=constants.Dirs.WEB, shell=constants.IS_WINDOWS, - show_logs=True, ) processes.show_status( "Installing frontend packages from config and components", process @@ -728,8 +696,8 @@ def check_schema_up_to_date(): with model.Model.get_db_engine().connect() as connection: try: if model.Model.alembic_autogenerate( - connection=connection, - write_migration_scripts=False, + connection=connection, + write_migration_scripts=False, ): console.error( "Detected database schema changes. Run [bold]reflex db makemigrations[/bold] "