From dd5789fcd95544dfc848466a7fe227da830da385 Mon Sep 17 00:00:00 2001 From: zwitschi Date: Tue, 4 Aug 2026 19:43:39 +0200 Subject: [PATCH] feat: implement lazy loading for hls.js and enhance video player initialization --- CHANGELOG.md | 1 + frontend/src/main.ts | 29 +++++++++++++++++++---------- frontend/vite.config.ts | 1 + 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83fe50b..c07cfc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Updated chat runtime image to include ffmpeg/ffprobe for media duration probing on upload. - Rebuilt viewer, admin, and admin-login pages around custom semantic class structures with accessibility-focused landmarks, tab semantics, and keyboard-focus behavior. - Replaced legacy and Tailwind-based stylesheet rules with a custom design-token CSS system covering responsive layouts, forms, tables, and reduced-motion behavior. +- Code-split `hls.js` via lazy loading in the viewer bootstrap to shrink the main frontend bundle and isolate stream playback logic into a dedicated chunk. ### Fixed diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 906c456..9c22920 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -1,6 +1,7 @@ -import Hls from "hls.js"; import "./style.css"; +type HlsClass = typeof import("hls.js")["default"]; + declare global { interface Window { switchRoom: (room: string) => void; @@ -9,7 +10,7 @@ declare global { } } -let hls: Hls | null = null; +let hls: InstanceType | null = null; let ws: WebSocket | null = null; let currentRoom = "main"; let username = "viewer" + Math.floor(Math.random() * 1000); @@ -109,18 +110,26 @@ function addMessage( messages.scrollTop = messages.scrollHeight; } -function initPlayerAndChat() { +async function initPlayerAndChat() { const video = document.getElementById("player") as HTMLVideoElement; const manifestUrl = resolveManifestUrl(); - if (Hls.isSupported()) { - hls = new Hls(); - hls.loadSource(manifestUrl); - hls.attachMedia(video); - hls.on(Hls.Events.MANIFEST_PARSED, () => video.play()); - } else if (video.canPlayType("application/vnd.apple.mpegurl")) { + if (video.canPlayType("application/vnd.apple.mpegurl")) { video.src = manifestUrl; video.addEventListener("loadedmetadata", () => video.play()); + } else { + try { + const { default: Hls } = await import("hls.js"); + if (Hls.isSupported()) { + hls = new Hls(); + hls.loadSource(manifestUrl); + hls.attachMedia(video); + hls.on(Hls.Events.MANIFEST_PARSED, () => video.play()); + } + } catch (error) { + console.error("Failed to load HLS player", error); + addMessage("system", "Unable to initialize video player."); + } } connectWebSocket("main"); @@ -183,5 +192,5 @@ window.sendMessage = sendMessage; window.togglePrivateDM = togglePrivateDM; document.addEventListener("DOMContentLoaded", () => { - initPlayerAndChat(); + void initPlayerAndChat(); }); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 2ea4e8a..3205d60 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from "vite"; export default defineConfig({ envDir: "..", build: { + chunkSizeWarningLimit: 600, rollupOptions: { input: { main: "index.html",