From b9cffc7d3f47fc617c3623cb258dfccb0ea45f00 Mon Sep 17 00:00:00 2001 From: forge Date: Tue, 7 Jul 2026 11:21:17 +0000 Subject: [PATCH] perf(ads): preconnect + preload Slise embed so banners render as the page loads Banners were blank for ~1s after page load because the Slise embed script was only injected inside AdBanner's onMounted (after the app bundle booted and the component mounted) over a cold connection with no resource hints. - index.html: preconnect/dns-prefetch the Slise origin and preload embed.js, so the ~21KB script downloads in parallel with the app bundle instead of ~1s later. Measured on a local build: embed.js request start moves from ~1013ms to ~14ms after navigation. - AdBanner.vue: fill the slot on the script's `load` event instead of a one-shot `typeof adsbyslisesync === 'function'` check that silently skipped the first banner (the function isn't defined yet right after the async script is appended). The first ad now fills the moment the script is ready rather than waiting for Slise's internal 1s location poll. Co-Authored-By: Claude Opus 4.8 (1M context) --- index.html | 6 ++++++ src/components/ad/AdBanner.vue | 32 ++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 1e0a85d58b..764107f0f6 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,12 @@ + + + + Ping Dashboard - Cosmos Blockchain Explorer And Web Wallet { observer.observe(containerRef.value); } - // Load script only once - if (!document.querySelector('script[src="https://v1.slise.xyz/scripts/embed.js"]')) { + // Queue this slot for Slise. + window.adsbyslise = window.adsbyslise || []; + window.adsbyslise.push({ slot: props.slot }); + + // Fill the slot as soon as Slise's embed script is ready. Waiting for the + // script's `load` event (instead of a one-shot check) means the very first + // banner fills the moment the script arrives, rather than only on Slise's + // internal 1s location poll. + const sync = () => window.adsbyslisesync?.(); + const existing = document.querySelector(`script[src="${SLISE_EMBED_SRC}"]`); + + if (window.adsbyslisesync) { + sync(); + } else if (existing) { + existing.addEventListener('load', sync, { once: true }); + } else { const script = document.createElement('script'); - script.src = 'https://v1.slise.xyz/scripts/embed.js'; + script.src = SLISE_EMBED_SRC; script.async = true; + script.addEventListener('load', sync, { once: true }); document.head.appendChild(script); } - - // Initialize ad queue - window.adsbyslise = window.adsbyslise || []; - window.adsbyslise.push({ slot: props.slot }); - - // Sync if available - if (typeof window.adsbyslisesync === 'function') { - window.adsbyslisesync(); - } }); onBeforeUnmount(() => {