Initial Diagnosis: The Hidden Bottlenecks Behind a 66 Score
For most web engineers, performance optimization advice is often reduced to cliché bullet points like 'compress images' or 'minify your code'. However, testing a modern React or TanStack Start application under mobile emulation (throttled 4G / simulated CPU slowdown) with Google Lighthouse frequently reveals a disappointing score in the 60s, with Largest Contentful Paint (LCP) climbing beyond 7 seconds.
Capturing a granular Performance trace in Chrome DevTools revealed that raw image size was merely a symptom. The real culprits were three structural architectural bottlenecks: 1) A third-party script blocking the critical rendering path for 180 ms, 2) All blog post markdown bodies (137 KB) being accidentally bundled into the initial client bundle, and 3) Third-party analytics executing eagerly on page boot.
# Lighthouse Mobil Lantern Simülasyonu (Önceki Durum):
# Performans Skoru: 66 / 100
# FCP (First Contentful Paint): 3.1 s
# LCP (Largest Contentful Paint): 7.7 s
# TBT (Total Blocking Time): 520 ms
# Render-blocking kaynaklar: 180 ms gecikmeThe Invisible Render-Blocking Trap: Cloudflare's email-decode.min.js
Deep in server-rendered HTML payloads lurks an invisible performance killer: Cloudflare's 'Email Address Obfuscation' feature. When your server renders a literal 'mailto:user [at] domain.com' pattern, Cloudflare's edge proxy rewrites the link and injects a synchronous external script tag pointing to 'email-decode.min.js' at the bottom of the body.
On mobile 4G networks, fetching and executing this script adds a 170–180 ms render-blocking delay. The solution is straightforward: never render raw 'mailto:' attributes in server-side markup. By assembling the email address client-side upon explicit user action (click/copy) rather than in the raw SSR string, Cloudflare never triggers the rewrite, eliminating the render-blocking script entirely.
// ÖNCE (ZARARLI): Düz e-posta href'i Cloudflare email-decode.min.js enjekte eder
<a href={"mailto:kullanici" + " [at] " + "alanadi.com"}>İletişim</a>
// SONRA (SIFIR BLOKAJ): Dinamik tetikleme ve bot-proof montaj
const EMAIL = ["kullanici", "alanadi.com"].join(String.fromCharCode(64));
<a href="/contact" onClick={(e) => { e.preventDefault(); window.location.href = `mailto:${EMAIL}`; }}>
{EMAIL}
</a>Decoupling Heavy Content: Virtual Module Code-Splitting
A common architecture pitfall in modern full-stack frameworks is importing complete content payloads into global route loaders. When a homepage loader references a monolithic content array, the bundler statically inlines all markdown/JSON article bodies directly into the shared client entry chunk.
Visitors loading the homepage were forced to download hundreds of kilobytes of unread articles. We resolved this by engineering a custom Vite virtual module plugin (cmsContentPlugin). The entry chunk only includes a lightweight 'postIndex' metadata catalog (slugs, titles, reading minutes), while full article bodies are strictly deferred to route-level dynamic imports ('await import(...)').
// scripts/cms-content-plugin.ts (Özet Mantık)
export function cmsContentPlugin(): Plugin {
return {
name: "published-cms-content",
resolveId(id) {
if (id === "virtual:site-posts") return "\0virtual:site-posts";
if (id === "virtual:site-index") return "\0virtual:site-index";
},
load(id) {
if (id === "\0virtual:site-index") {
// Sadece hafif kart metadatasını dışa aktar (5 KB)
return `export const postIndex = ${JSON.stringify(lightweightMetadata)};`;
}
if (id === "\0virtual:site-posts") {
// Tam makale gövdeleri sadece talep edildiğinde ayrı chunk'a ayrılır (137 KB)
return `export const posts = ${JSON.stringify(fullArticles)};`;
}
}
};
}Zeroing Analytics Overhead: Interaction-Deferred Loading & Reverse Proxy
Third-party telemetry SDKs are notorious for inflating Total Blocking Time (TBT). Executing heavy analytics suites on the initial load event hogs the main thread during hydration, turning a potentially snappy page into an unresponsive frozen viewport on low-end devices.
We tackled this by implementing an interaction-deferred pattern. Rather than initializing PostHog eagerly on DOMContentLoaded, we attach passive one-time listeners to user gestures ('pointerdown', 'scroll', 'touchstart'). The SDK is fetched asynchronously during browser idle time, reducing initial analytical TBT to exactly 0 ms.
To combat tracking drop-offs caused by ad blockers (uBlock Origin, Brave Shields), we configured a server-side reverse proxy on Vercel (/ingest rewrites). Traffic flows through 'umutgungorr.com/ingest', qualifying as trusted first-party telemetry while eliminating data loss.
// Vercel Ters Proxy (vercel.json):
{
"rewrites": [
{
"source": "/ingest/static/:path*",
"destination": "https://eu-assets.i.posthog.com/static/:path*"
},
{
"source": "/ingest/:path*",
"destination": "https://eu.i.posthog.com/:path*"
}
]
}
// İlk Etkileşimde Asenkron Başlatma (src/lib/posthog.ts):
const INTERACTION_EVENTS = ["pointerdown", "touchstart", "scroll", "click"];
function initOnFirstInteraction() {
const onInteract = () => {
INTERACTION_EVENTS.forEach(e => window.removeEventListener(e, onInteract));
requestIdleCallback(() => void import("posthog-js").then(mod => mod.default.init(...)));
};
INTERACTION_EVENTS.forEach(e => window.addEventListener(e, onInteract, { once: true, passive: true }));
}Results: 100/100 Desktop & 98 Mobile Real-World Metrics
Running rigorous Lighthouse audits in the live production environment following these targeted architectural refinements yielded the following verified metrics:
Desktop Lighthouse achieved a flawless 100 / 100 (FCP: 0.5s, LCP: 0.6s, TBT: 0ms, CLS: 0). Mobile performance jumped from 66 to 98 / 100, slashing LCP from 7.7s to 2.1s and TBT to near zero—all accomplished without removing a single visual element, glassmorphic card, or motion animation.
# Optimizasyon Öncesi vs Sonrası Karşılaştırma Tablosu:
# ------------------------------------------------------------
# Metrik | Önceki Değer | Optimizasyon Sonrası
# ------------------------------------------------------------
# Mobil Lighthouse | 66 / 100 | 98 / 100 (Yeşil)
# Masaüstü Lighthouse | 84 / 100 | 100 / 100 (Kusursuz)
# Mobil LCP | 7.7 s | 2.1 s (↓ %72 Hızlı)
# Mobil FCP | 3.1 s | 1.8 s (↓ %42 Hızlı)
# Total Blocking Time | 520 ms | 0 - 50 ms
# Render-Blocking JS | 180 ms | 0 ms (Kaldırıldı)
# Ad Blocker Veri Kaybı | %25 - %30 | %0 (Ters Proxy ile)Source: Google Chrome Developers: Optimize Largest Contentful Paint
Source: PostHog Docs: Reverse Proxy on Vercel
Source: TanStack Router: Preloading and Router State Optimization
