From d3d6561f4d81fe1ff4a7039f633e5b1331b9a866 Mon Sep 17 00:00:00 2001 From: radishzzz Date: Thu, 8 May 2025 01:24:03 +0100 Subject: [PATCH] perf: optimize loading timing for github cards and lightbox, clean up redundant head tags, and improve css organization --- src/components/Widgets/GithubCard.astro | 99 ++++++++++++++----------- src/components/Widgets/PhotoSwipe.astro | 82 +++++++++++--------- src/layouts/Head.astro | 13 +--- src/layouts/Layout.astro | 6 +- src/styles/extend.css | 14 +++- src/styles/global.css | 10 +-- src/styles/heti.css | 10 +-- 7 files changed, 124 insertions(+), 110 deletions(-) diff --git a/src/components/Widgets/GithubCard.astro b/src/components/Widgets/GithubCard.astro index f5804e3..e7ee6a2 100644 --- a/src/components/Widgets/GithubCard.astro +++ b/src/components/Widgets/GithubCard.astro @@ -4,54 +4,65 @@ function setupGithubCards() { if (githubCards.length === 0) return - githubCards.forEach(async (card) => { - const repo = (card as HTMLElement).dataset.repo - if (!repo) - return - - const avatarEl = card.querySelector('.gc-owner-avatar') as HTMLElement - const descEl = card.querySelector('.gc-repo-description') as HTMLElement - const starsEl = card.querySelector('.gc-stars-count') as HTMLElement - const forksEl = card.querySelector('.gc-forks-count') as HTMLElement - const licenseEl = card.querySelector('.gc-license-info') as HTMLElement - - try { - const response = await fetch(`https://api.github.com/repos/${repo}`) - if (response.ok) { - const data = await response.json() - - if (avatarEl && data.owner?.avatar_url) - avatarEl.style.backgroundImage = `url(${data.owner.avatar_url})` - - if (descEl && data.description) - descEl.textContent = data.description - - if (starsEl) { - starsEl.textContent = new Intl.NumberFormat('en', { - notation: 'compact', - maximumFractionDigits: 1, - }).format(data.stargazers_count) - } - - if (forksEl) { - forksEl.textContent = new Intl.NumberFormat('en', { - notation: 'compact', - maximumFractionDigits: 1, - }).format(data.forks_count) - } - - if (licenseEl) - licenseEl.textContent = data.license?.spdx_id || 'No License' + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + loadCardData(entry.target as HTMLElement) + observer.unobserve(entry.target) } - else { - if (descEl) - descEl.textContent = 'Loading failed.' + }) + }, { rootMargin: '200px' }) + + githubCards.forEach(card => observer.observe(card)) +} + +async function loadCardData(card: HTMLElement) { + const repo = card.dataset.repo + if (!repo) + return + + const avatarEl = card.querySelector('.gc-owner-avatar') as HTMLElement + const descEl = card.querySelector('.gc-repo-description') as HTMLElement + const starsEl = card.querySelector('.gc-stars-count') as HTMLElement + const forksEl = card.querySelector('.gc-forks-count') as HTMLElement + const licenseEl = card.querySelector('.gc-license-info') as HTMLElement + + try { + const response = await fetch(`https://api.github.com/repos/${repo}`) + if (response.ok) { + const data = await response.json() + + if (avatarEl && data.owner?.avatar_url) + avatarEl.style.backgroundImage = `url(${data.owner.avatar_url})` + + if (descEl && data.description) + descEl.textContent = data.description + + if (starsEl) { + starsEl.textContent = new Intl.NumberFormat('en', { + notation: 'compact', + maximumFractionDigits: 1, + }).format(data.stargazers_count) } + + if (forksEl) { + forksEl.textContent = new Intl.NumberFormat('en', { + notation: 'compact', + maximumFractionDigits: 1, + }).format(data.forks_count) + } + + if (licenseEl) + licenseEl.textContent = data.license?.spdx_id || 'No License' } - catch { - console.error(`Failed to fetch ${repo}`) + else { + if (descEl) + descEl.textContent = 'Loading failed.' } - }) + } + catch { + console.error(`Failed to fetch ${repo}`) + } } setupGithubCards() diff --git a/src/components/Widgets/PhotoSwipe.astro b/src/components/Widgets/PhotoSwipe.astro index c162dc1..2a2039e 100644 --- a/src/components/Widgets/PhotoSwipe.astro +++ b/src/components/Widgets/PhotoSwipe.astro @@ -7,48 +7,62 @@ const pswp = import('photoswipe') function setupPhotoSwipe() { const bodyElement = document.body - if (!bodyElement.hasAttribute('data-photoswipe-initialized')) { - lightbox = new PhotoSwipeLightbox({ - gallery: 'article.heti img', - pswpModule: () => pswp, - bgOpacity: 0.9, - padding: { - top: window.innerHeight * 0.1, - bottom: window.innerHeight * 0.1, - left: window.innerWidth * 0.073, - right: window.innerWidth * 0.073, - }, - zoom: false, - close: false, - wheelToZoom: true, - imageClickAction: 'close', - tapAction: 'close', - }) + if (bodyElement.hasAttribute('data-photoswipe-initialized')) + return - // Set image dimensions - lightbox.addFilter('domItemData', (itemData, element) => { - if (element instanceof HTMLImageElement) { - // Set image source - itemData.src = element.src + const images = document.querySelectorAll('article.heti img') + if (images.length === 0) + return - // Set dimensions with fallback to window size - itemData.w = Number(element.naturalWidth || window.innerWidth) - itemData.h = Number(element.naturalHeight || window.innerHeight) + lightbox = new PhotoSwipeLightbox({ + gallery: 'article.heti img', + pswpModule: () => pswp, + bgOpacity: 0.9, + padding: { + top: window.innerHeight * 0.1, + bottom: window.innerHeight * 0.1, + left: window.innerWidth * 0.073, + right: window.innerWidth * 0.073, + }, + zoom: false, + close: false, + wheelToZoom: true, + imageClickAction: 'close', + tapAction: 'close', + }) - // Set thumbnail source - itemData.msrc = element.src - } - return itemData - }) + // Set image dimensions + lightbox.addFilter('domItemData', (itemData, element) => { + if (element instanceof HTMLImageElement) { + // Set image source + itemData.src = element.src - lightbox.init() + // Set dimensions with fallback to window size + itemData.w = Number(element.naturalWidth || window.innerWidth) + itemData.h = Number(element.naturalHeight || window.innerHeight) - bodyElement.setAttribute('data-photoswipe-initialized', 'true') + // Set thumbnail source + itemData.msrc = element.src + } + return itemData + }) + + lightbox.init() + + bodyElement.setAttribute('data-photoswipe-initialized', 'true') +} + +function lazySetupPhotoSwipe() { + if ('requestIdleCallback' in window) { + window.requestIdleCallback(() => setupPhotoSwipe(), { timeout: 1000 }) + } + else { + setTimeout(setupPhotoSwipe, 100) } } -setupPhotoSwipe() -document.addEventListener('astro:page-load', setupPhotoSwipe) +lazySetupPhotoSwipe() +document.addEventListener('astro:page-load', lazySetupPhotoSwipe)