@@ -184,7 +184,16 @@ window.cancelAnimFrame = (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lazyObserver) {
|
||||
// Chromium fix: always disconnect the old observer before creating a new one.
|
||||
// Chromium holds detached DOM nodes in an IntersectionObserver alive much longer
|
||||
// than Firefox does. If we reuse a stale observer after an AJAX content swap,
|
||||
// Chromium can fire callbacks for old detached nodes, causing duplicate image
|
||||
// fetches and flooding the network. Disconnecting releases those references.
|
||||
if (lazyObserver) {
|
||||
lazyObserver.disconnect();
|
||||
lazyObserver = null;
|
||||
}
|
||||
|
||||
lazyObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
@@ -237,7 +246,6 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
});
|
||||
}, { rootMargin: '300px 0px', threshold: 0.01 });
|
||||
}
|
||||
|
||||
// Nudge lazy loading on tab switch to prevent stuck skeletons in inactive tabs
|
||||
if (!window._lazyVisibilityBound) {
|
||||
@@ -254,7 +262,10 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
|
||||
document.querySelectorAll('.lazy-thumb').forEach(thumb => {
|
||||
if (!thumb.dataset.lazyObserved) {
|
||||
// Reset lazyObserved on every initLazyLoading call so the fresh observer
|
||||
// picks up all unloaded thumbs regardless of previous observation state.
|
||||
delete thumb.dataset.lazyObserved;
|
||||
if (!thumb.classList.contains('loaded')) {
|
||||
thumb.dataset.lazyObserved = 'true';
|
||||
lazyObserver.observe(thumb);
|
||||
}
|
||||
|
||||
@@ -535,6 +535,17 @@ process.on('uncaughtException', err => {
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Thumbnails (/t/) and covers (/ca/) are static WebP files that never change at a
|
||||
// given URL — the client appends a ?t= cache-bust param when a thumb is regenerated.
|
||||
// Without an explicit Cache-Control header, Chromium treats these as uncacheable and
|
||||
// re-fetches every visible thumbnail on every AJAX navigation, causing severe lag.
|
||||
// Firefox uses a more lenient heuristic and caches them anyway — hence the difference.
|
||||
if (req.url.pathname.match(/^\/(t|ca)\//)) {
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
} else if (req.url.pathname.match(/^\/(b|a|memes)\//)) {
|
||||
// Full-size images and avatars: cache for 1 hour, re-validate after
|
||||
res.setHeader('Cache-Control', 'public, max-age=3600');
|
||||
}
|
||||
return;
|
||||
}
|
||||
const availableThemes = cfg.websrv.themes || ['amoled', 'atmos', 'f0ck', 'f0ck95d', 'iced', 'orange', 'p1nk', '4d'];
|
||||
|
||||
Reference in New Issue
Block a user