1import { createRoot } from 'react-dom/client'; 2import { html } from './html.js?v=3.8.36'; 3import App from './App.js?v=3.8.36'; 4import { registerArchiveSiteTools } from './services/siteTools.js?v=3.8.36'; 5import { logWatchdog } from './utils/consoleWatchdog.js?v=3.8.36'; 6import { installTypewriterEgg } from './services/typewriterEgg.js?v=3.8.36'; 7 8const rootElement = document.getElementById('root'); 9if (!rootElement) { 10 throw new Error("Could not find root element to mount to"); 11} 12 13const root = createRoot(rootElement); 14root.render(html`<${App} />`); 15 16// Hidden extras (#754): the console watchdog barks once per load, and the 17// typewriter waits for its sequence. Both are additive, silent, and wrapped so 18// a failure here can never take down the app mounted above. 19try { 20 logWatchdog(); 21 installTypewriterEgg(); 22} catch { 23 // An archive that loads matters more than an extra that does not. 24} 25 26// WebMCP is progressive enhancement. Supporting browsers receive structured, 27// read-only archive tools. Every other browser continues with the same app. 28registerArchiveSiteTools() 29 .catch(error => console.warn('[site tools] registration failed:', error.message)); 30 31// Opt-in client-side performance instrumentation (#280). Off by default; 32// enable with `localStorage.jrda_debug = '1'` in DevTools and reload (the #170 33// toggle). Everything below is gated so production never loads web-vitals or 34// registers an observer, and a CDN hiccup or storage-policy throw cannot break 35// the app mounted above. 36function perfDebugEnabled() { 37 try { 38 return typeof localStorage !== 'undefined' && localStorage.getItem('jrda_debug') === '1'; 39 } catch { 40 return false; 41 } 42} 43 44if (perfDebugEnabled()) { 45 // Log the custom data-load measure emitted around fetchCoreData (App.js). 46 // buffered:true replays the measure even if it lands before this registers. 47 try { 48 new PerformanceObserver((list) => { 49 for (const entry of list.getEntries()) { 50 // Only data:load lands here today; the prefix keeps any future data:* 51 // measures in scope without re-touching this observer. 52 if (entry.name.startsWith('data:')) { 53 console.log(`[perf] ${entry.name}: ${Math.round(entry.duration)}ms`); 54 } 55 } 56 }).observe({ type: 'measure', buffered: true }); 57 } catch (err) { 58 console.warn('[perf] measure observer unavailable:', err); 59 } 60 61 // Core Web Vitals (LCP/INP/CLS), console-only -- no analytics SDK. Dynamic 62 // import so the ~1.5 KB module is fetched only when the flag is on. 63 import('https://esm.sh/[email protected]') 64 .then(({ onLCP, onINP, onCLS }) => { 65 onLCP((m) => console.log('[perf] LCP:', Math.round(m.value))); 66 onINP((m) => console.log('[perf] INP:', Math.round(m.value))); 67 onCLS((m) => console.log('[perf] CLS:', Number(m.value.toFixed(4)))); 68 }) 69 .catch((err) => console.warn('[perf] web-vitals failed to load:', err)); 70}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.