Simplify webui Vite asset injection

pull/388/head
Antti Kettunen 2 months ago
parent ed8ff46c9c
commit 736f243d5c
No known key found for this signature in database
GPG Key ID: C6B2A3D250359BD7

@ -372,22 +372,14 @@ def _log_rejected_socketio_origin():
)
# --- WebUI asset injection ---
_webui_react_manifest = None
_webui_react_manifest_mtime = None
_webui_react_manifest_path = Path(base_dir) / 'webui' / 'static' / 'dist' / '.vite' / 'manifest.json'
_webui_vite_manifest = None
_webui_vite_manifest_mtime = None
_webui_vite_entry = 'src/app/main.tsx'
_webui_vite_manifest_path = Path(base_dir) / 'webui' / 'static' / 'dist' / '.vite' / 'manifest.json'
_webui_vite_dev = os.environ.get('SOULSYNC_WEBUI_VITE_DEV', '').lower() in ('1', 'true', 'yes', 'on')
_webui_vite_url = os.environ.get('SOULSYNC_WEBUI_VITE_URL', 'http://127.0.0.1:5173').rstrip('/')
_webui_vite_base = '/static/dist/'
_webui_react_apps = {
'router': {
'entry': 'src/app/main.tsx',
'dev_entry': 'src/app/main.tsx',
'mount_id': None,
'mount_class': None,
},
}
_webui_client_route_map = {
'/dashboard': 'dashboard',
'/sync': 'sync',
@ -449,53 +441,52 @@ def _should_serve_webui_spa(pathname: str) -> bool:
return not normalized.startswith(excluded_prefixes)
def _load_webui_react_manifest():
global _webui_react_manifest, _webui_react_manifest_mtime
def _webui_vite_dev_asset_url(asset_path: str) -> str:
return f'{_webui_vite_url}{_webui_vite_base.rstrip("/")}/{asset_path.lstrip("/")}'
def _load_webui_vite_manifest():
global _webui_vite_manifest, _webui_vite_manifest_mtime
manifest_mtime = None
if _webui_react_manifest_path.exists():
if _webui_vite_manifest_path.exists():
try:
manifest_mtime = _webui_react_manifest_path.stat().st_mtime
manifest_mtime = _webui_vite_manifest_path.stat().st_mtime
except OSError:
manifest_mtime = None
if _webui_react_manifest is not None and manifest_mtime == _webui_react_manifest_mtime:
return _webui_react_manifest
if _webui_vite_manifest is not None and manifest_mtime == _webui_vite_manifest_mtime:
return _webui_vite_manifest
if _webui_react_manifest_path.exists():
if _webui_vite_manifest_path.exists():
try:
with _webui_react_manifest_path.open('r', encoding='utf-8') as handle:
_webui_react_manifest = json.load(handle)
_webui_react_manifest_mtime = manifest_mtime
with _webui_vite_manifest_path.open('r', encoding='utf-8') as handle:
_webui_vite_manifest = json.load(handle)
_webui_vite_manifest_mtime = manifest_mtime
except Exception as exc:
logger.warning(f"Failed to load webui manifest: {exc}")
_webui_react_manifest = {}
_webui_react_manifest_mtime = manifest_mtime
_webui_vite_manifest = {}
_webui_vite_manifest_mtime = manifest_mtime
else:
_webui_react_manifest = {}
_webui_react_manifest_mtime = None
return _webui_react_manifest
_webui_vite_manifest = {}
_webui_vite_manifest_mtime = None
return _webui_vite_manifest
def _build_webui_react_assets(app_name='issues', placement='body'):
app_config = _webui_react_apps.get(app_name)
if not app_config:
return ''
def _build_webui_vite_assets(placement='body'):
if placement not in ('head', 'body'):
return ''
if _webui_vite_dev:
if placement == 'head':
return ''
vite_base_url = f'{_webui_vite_url}{_webui_vite_base.rstrip("/")}'
return '\n'.join([
f'<script type="module" src="{vite_base_url}/@vite/client"></script>',
f'<script type="module" src="{vite_base_url}/{app_config["dev_entry"]}"></script>',
])
f'<script type="module" src="{_webui_vite_dev_asset_url("@vite/client")}"></script>',
f'<script type="module" src="{_webui_vite_dev_asset_url(_webui_vite_entry)}"></script>',
])
manifest = _load_webui_react_manifest()
entry = manifest.get(app_config['entry'])
manifest = _load_webui_vite_manifest()
entry = manifest.get(_webui_vite_entry)
if not entry:
return ''
@ -506,30 +497,15 @@ def _build_webui_react_assets(app_name='issues', placement='body'):
return '\n'.join(head_assets)
entry_file = entry.get('file')
return f'<script type="module" src="{url_for("static", filename=f"dist/{entry_file}")}"></script>'
def _build_webui_react_root(app_name='issues'):
app_config = _webui_react_apps.get(app_name)
if not app_config:
if not entry_file:
return ''
mount_id = app_config.get('mount_id', f'{app_name}-app-root')
mount_class = app_config.get('mount_class', f'{app_name}-app-root')
if not mount_id:
return ''
return f'<div id="{mount_id}" class="{mount_class}" data-react-app="{app_name}"></div>'
return f'<script type="module" src="{url_for("static", filename=f"dist/{entry_file}")}"></script>'
@app.context_processor
def inject_webui_assets():
return {
'react_assets_for': lambda app_name='issues', placement='body': _build_webui_react_assets(app_name, placement),
'react_root': lambda app_name='issues': _build_webui_react_root(app_name),
# Transitional aliases for older templates while the route contract settles.
'react_head_assets': lambda app_name='issues': _build_webui_react_assets(app_name, 'head'),
'react_body_assets': lambda app_name='issues': _build_webui_react_assets(app_name, 'body'),
'react_mount': lambda app_name='issues': _build_webui_react_root(app_name),
'vite_assets': _build_webui_vite_assets,
}
# --- Profile Context (before_request hook) ---

@ -12,7 +12,7 @@
<link rel="stylesheet" href="{{ url_for('static', filename='style.css', v=static_v) }}">
<link rel="stylesheet" href="{{ url_for('static', filename='mobile.css', v=static_v) }}">
<link rel="stylesheet" href="{{ url_for('static', filename='setup-wizard.css', v=static_v) }}">
{{ react_assets_for('router', 'head')|safe }}
{{ vite_assets('head')|safe }}
</head>
<body>
@ -7775,8 +7775,7 @@
<script src="{{ url_for('static', filename='vendor/socket.io.min.js', v=static_v) }}"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
{{ react_assets_for('router', 'body')|safe }}
{{ react_assets_for('issues', 'body')|safe }}
{{ vite_assets('body')|safe }}
<script src="{{ url_for('static', filename='setup-wizard.js', v=static_v) }}"></script>
<!-- Split modules (was: script.js) — core.js must load first, init.js last -->
<script src="{{ url_for('static', filename='core.js', v=static_v) }}"></script>

Loading…
Cancel
Save