Simplify webui Vite asset injection
This commit is contained in:
parent
ed8ff46c9c
commit
736f243d5c
2 changed files with 34 additions and 59 deletions
|
|
@ -372,22 +372,14 @@ def _log_rejected_socketio_origin():
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- WebUI asset injection ---
|
# --- WebUI asset injection ---
|
||||||
_webui_react_manifest = None
|
_webui_vite_manifest = None
|
||||||
_webui_react_manifest_mtime = None
|
_webui_vite_manifest_mtime = None
|
||||||
_webui_react_manifest_path = Path(base_dir) / 'webui' / 'static' / 'dist' / '.vite' / 'manifest.json'
|
_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_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_url = os.environ.get('SOULSYNC_WEBUI_VITE_URL', 'http://127.0.0.1:5173').rstrip('/')
|
||||||
_webui_vite_base = '/static/dist/'
|
_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 = {
|
_webui_client_route_map = {
|
||||||
'/dashboard': 'dashboard',
|
'/dashboard': 'dashboard',
|
||||||
'/sync': 'sync',
|
'/sync': 'sync',
|
||||||
|
|
@ -449,53 +441,52 @@ def _should_serve_webui_spa(pathname: str) -> bool:
|
||||||
return not normalized.startswith(excluded_prefixes)
|
return not normalized.startswith(excluded_prefixes)
|
||||||
|
|
||||||
|
|
||||||
def _load_webui_react_manifest():
|
def _webui_vite_dev_asset_url(asset_path: str) -> str:
|
||||||
global _webui_react_manifest, _webui_react_manifest_mtime
|
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
|
manifest_mtime = None
|
||||||
if _webui_react_manifest_path.exists():
|
if _webui_vite_manifest_path.exists():
|
||||||
try:
|
try:
|
||||||
manifest_mtime = _webui_react_manifest_path.stat().st_mtime
|
manifest_mtime = _webui_vite_manifest_path.stat().st_mtime
|
||||||
except OSError:
|
except OSError:
|
||||||
manifest_mtime = None
|
manifest_mtime = None
|
||||||
|
|
||||||
if _webui_react_manifest is not None and manifest_mtime == _webui_react_manifest_mtime:
|
if _webui_vite_manifest is not None and manifest_mtime == _webui_vite_manifest_mtime:
|
||||||
return _webui_react_manifest
|
return _webui_vite_manifest
|
||||||
|
|
||||||
if _webui_react_manifest_path.exists():
|
if _webui_vite_manifest_path.exists():
|
||||||
try:
|
try:
|
||||||
with _webui_react_manifest_path.open('r', encoding='utf-8') as handle:
|
with _webui_vite_manifest_path.open('r', encoding='utf-8') as handle:
|
||||||
_webui_react_manifest = json.load(handle)
|
_webui_vite_manifest = json.load(handle)
|
||||||
_webui_react_manifest_mtime = manifest_mtime
|
_webui_vite_manifest_mtime = manifest_mtime
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning(f"Failed to load webui manifest: {exc}")
|
logger.warning(f"Failed to load webui manifest: {exc}")
|
||||||
_webui_react_manifest = {}
|
_webui_vite_manifest = {}
|
||||||
_webui_react_manifest_mtime = manifest_mtime
|
_webui_vite_manifest_mtime = manifest_mtime
|
||||||
else:
|
else:
|
||||||
_webui_react_manifest = {}
|
_webui_vite_manifest = {}
|
||||||
_webui_react_manifest_mtime = None
|
_webui_vite_manifest_mtime = None
|
||||||
return _webui_react_manifest
|
return _webui_vite_manifest
|
||||||
|
|
||||||
|
|
||||||
def _build_webui_react_assets(app_name='issues', placement='body'):
|
def _build_webui_vite_assets(placement='body'):
|
||||||
app_config = _webui_react_apps.get(app_name)
|
|
||||||
if not app_config:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
if placement not in ('head', 'body'):
|
if placement not in ('head', 'body'):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
if _webui_vite_dev:
|
if _webui_vite_dev:
|
||||||
if placement == 'head':
|
if placement == 'head':
|
||||||
return ''
|
return ''
|
||||||
vite_base_url = f'{_webui_vite_url}{_webui_vite_base.rstrip("/")}'
|
|
||||||
return '\n'.join([
|
return '\n'.join([
|
||||||
f'<script type="module" src="{vite_base_url}/@vite/client"></script>',
|
f'<script type="module" src="{_webui_vite_dev_asset_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(_webui_vite_entry)}"></script>',
|
||||||
])
|
])
|
||||||
|
|
||||||
manifest = _load_webui_react_manifest()
|
manifest = _load_webui_vite_manifest()
|
||||||
entry = manifest.get(app_config['entry'])
|
entry = manifest.get(_webui_vite_entry)
|
||||||
if not entry:
|
if not entry:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
@ -506,30 +497,15 @@ def _build_webui_react_assets(app_name='issues', placement='body'):
|
||||||
return '\n'.join(head_assets)
|
return '\n'.join(head_assets)
|
||||||
|
|
||||||
entry_file = entry.get('file')
|
entry_file = entry.get('file')
|
||||||
|
if not entry_file:
|
||||||
|
return ''
|
||||||
return f'<script type="module" src="{url_for("static", filename=f"dist/{entry_file}")}"></script>'
|
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:
|
|
||||||
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>'
|
|
||||||
|
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_webui_assets():
|
def inject_webui_assets():
|
||||||
return {
|
return {
|
||||||
'react_assets_for': lambda app_name='issues', placement='body': _build_webui_react_assets(app_name, placement),
|
'vite_assets': _build_webui_vite_assets,
|
||||||
'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),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Profile Context (before_request hook) ---
|
# --- 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='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='mobile.css', v=static_v) }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='setup-wizard.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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -7775,8 +7775,7 @@
|
||||||
|
|
||||||
<script src="{{ url_for('static', filename='vendor/socket.io.min.js', v=static_v) }}"></script>
|
<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>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
|
||||||
{{ react_assets_for('router', 'body')|safe }}
|
{{ vite_assets('body')|safe }}
|
||||||
{{ react_assets_for('issues', 'body')|safe }}
|
|
||||||
<script src="{{ url_for('static', filename='setup-wizard.js', v=static_v) }}"></script>
|
<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 -->
|
<!-- 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>
|
<script src="{{ url_for('static', filename='core.js', v=static_v) }}"></script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue