Explorar o código

add explicit "exclude" parameter to setup empty routes

Falko Schindler %!s(int64=2) %!d(string=hai) anos
pai
achega
c5880585d9
Modificáronse 5 ficheiros con 46 adicións e 10 borrados
  1. 2 0
      README.md
  2. 3 2
      nicegui/config.py
  3. 2 0
      nicegui/nicegui.py
  4. 37 8
      nicegui/routes.py
  5. 2 0
      nicegui/run.py

+ 2 - 0
README.md

@@ -89,6 +89,8 @@ You can call `ui.run()` with optional arguments:
 - `uvicorn_reload_dirs`: string with comma-separated list for directories to be monitored (default is current working directory only)
 - `uvicorn_reload_includes`: string with comma-separated list of glob-patterns which trigger reload on modification (default: `'.py'`)
 - `uvicorn_reload_excludes`: string with comma-separated list of glob-patterns which should be ignored for reload (default: `'.*, .py[cod], .sw.*, ~*'`)
+- `exclude`: comma-separated string to exclude elements (with corresponding JavaScript libraries) to save bandwidth
+  (possible entries: chart, colors, custom_example, interactive_image, keyboard, log, joystick, scene, table)
 
 The environment variables `HOST` and `PORT` can also be used to configure NiceGUI.
 

+ 3 - 2
nicegui/config.py

@@ -1,6 +1,6 @@
 import os
-from dataclasses import dataclass
-from typing import Optional
+from dataclasses import dataclass, field
+from typing import List, Optional
 
 
 @dataclass
@@ -14,3 +14,4 @@ class Config():
     dark: Optional[bool] = False
     main_page_classes: str = 'q-ma-md column items-start'
     binding_refresh_interval: float = 0.1
+    excludes: List[str] = field(default_factory=list)

+ 2 - 0
nicegui/nicegui.py

@@ -13,6 +13,7 @@ if True:  # NOTE: prevent formatter from mixing up these lines
 from . import binding, globals
 from .page import create_page_routes, init_auto_index_page
 from .task_logger import create_task
+from .routes import create_exclude_routes
 from .timer import Timer
 
 jp.app.router.on_startup.clear()  # NOTE: remove JustPy's original startup function
@@ -31,6 +32,7 @@ def startup():
     globals.loop = asyncio.get_running_loop()
     init_auto_index_page()
     create_page_routes()
+    create_exclude_routes()
     globals.tasks.extend(create_task(t.coro, name=t.name) for t in Timer.prepared_coroutines)
     Timer.prepared_coroutines.clear()
     globals.tasks.extend(create_task(t, name='startup task')

+ 37 - 8
nicegui/routes.py

@@ -4,15 +4,13 @@ from functools import wraps
 from typing import List
 
 import justpy as jp
-from starlette import requests, routing
-from starlette.responses import FileResponse
-from starlette.routing import BaseRoute, Mount, Route
+from starlette.requests import Request
+from starlette.responses import FileResponse, PlainTextResponse
+from starlette.routing import BaseRoute, Mount, Route, compile_path
 from starlette.staticfiles import StaticFiles
 
 from . import globals
 from .helpers import is_coroutine
-from .page import Page
-from .task_logger import create_task
 
 
 def add_route(self, route: BaseRoute) -> None:
@@ -37,11 +35,11 @@ def get(self, path: str):
     :param path: string that starts with a '/'
     :return:
     """
-    *_, converters = routing.compile_path(path)
+    *_, converters = compile_path(path)
 
     def decorator(func):
         @wraps(func)
-        async def decorated(request: requests.Request):
+        async def decorated(request: Request):
             args = {name: converter.convert(request.path_params.get(name)) for name, converter in converters.items()}
             parameters = inspect.signature(func).parameters
             for key in parameters:
@@ -56,7 +54,7 @@ def get(self, path: str):
             if 'request' in parameters and 'request' not in args:
                 args['request'] = request
             return await func(**args) if is_coroutine(func) else func(**args)
-        self.add_route(routing.Route(path, decorated))
+        self.add_route(Route(path, decorated))
         return decorated
     return decorator
 
@@ -78,3 +76,34 @@ def add_dependencies(py_filepath: str, dependencies: List[str] = []) -> None:
         filename = os.path.basename(vue_filepath)
         jp.app.routes.insert(0, Route(f'/{filename}', lambda _: FileResponse(vue_filepath)))
         jp.component_file_list += [filename]
+
+
+def create_exclude_routes() -> None:
+    def void(_: Request) -> PlainTextResponse:
+        return PlainTextResponse()
+
+    if 'chart' in globals.config.excludes:
+        add_route(None, Route('/templates/local/highcharts.js', void))
+    if 'colors' in globals.config.excludes:
+        add_route(None, Route('/colors.js', void))
+    if 'custom_example' in globals.config.excludes:
+        add_route(None, Route('/custom_example.js', void))
+    if 'interactive_image' in globals.config.excludes:
+        add_route(None, Route('/interactive_image.js', void))
+    if 'keyboard' in globals.config.excludes:
+        add_route(None, Route('/keyboard.js', void))
+    if 'log' in globals.config.excludes:
+        add_route(None, Route('/log.js', void))
+    if 'joystick' in globals.config.excludes:
+        add_route(None, Route('/joystick.js', void))
+        add_route(None, Route('/lib/nipplejs.min.js', void))
+    if 'scene' in globals.config.excludes:
+        add_route(None, Route('/scene.js', void))
+        add_route(None, Route('/lib/CSS2DRenderer.js', void))
+        add_route(None, Route('/lib/CSS3DRenderer.js', void))
+        add_route(None, Route('/lib/OrbitControls.js', void))
+        add_route(None, Route('/lib/STLLoader.js', void))
+        add_route(None, Route('/lib/three.min.js', void))
+        add_route(None, Route('/lib/tween.umd.min.js', void))
+    if 'table' in globals.config.excludes:
+        add_route(None, Route('/templates/local/ag-grid-community.js', void))

+ 2 - 0
nicegui/run.py

@@ -30,6 +30,7 @@ def run(self, *,
         uvicorn_reload_dirs: str = '.',
         uvicorn_reload_includes: str = '*.py',
         uvicorn_reload_excludes: str = '.*, .py[cod], .sw.*, ~*',
+        exclude: str = '',
         ):
     globals.config = Config(
         host=host,
@@ -40,6 +41,7 @@ def run(self, *,
         dark=dark,
         main_page_classes=main_page_classes,
         binding_refresh_interval=binding_refresh_interval,
+        excludes=[e.strip() for e in exclude.split(',')],
     )
     os.environ['HOST'] = globals.config.host
     os.environ['PORT'] = str(globals.config.port)