Performance
Mar 2026·6 min read

Zero-JavaScript Thresholds: Strategic Code-Splitting and Asset Loading for Sub-Second LCP

Critical rendering path optimization, font preloading, fetch priority for hero elements, dynamic component imports, and tree-shaking heavy third-party dependencies.

LEP
Lelianto Eko PradanaAI & Full Stack Engineer · Indonesia

Introduction

Largest Contentful Paint (LCP) measures when the largest visual element above the fold (typically a hero banner image, headline text block, or video poster) becomes fully rendered.

A common pitfall in single-page React applications is requiring the browser to download, parse, and execute hundreds of kilobytes of JavaScript before the hero element can even begin loading. Start with the HTML, CSS, font, and image that make the first viewport useful; every other byte should earn its place.

The examples below are starting points, not universal defaults. fetchpriority="high" belongs on the actual LCP candidate—not every image—and preloading a font can hurt if that font is not used above the fold.


1. Optimizing Asset Fetch Priority

Tell the browser explicitly which resources are required for initial render using fetchpriority="high" and preloading critical web fonts:

html
<!-- Preload critical web font with display=swap -->
<link
  rel="preload"
  href="/fonts/inter-var.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

<!-- Hero image with explicit high priority -->
<img
  src="/hero-banner.webp"
  alt="Platform Preview"
  fetchpriority="high"
  loading="eager"
  width="1200"
  height="630"
/>

2. Lazy Loading Heavy Offscreen Components

Heavy components below the fold—such as interactive charts, code editors, or complex video players—should never bloat your initial JavaScript bundle.

Use Next.js dynamic() or React lazy() with Suspense:

tsx
import dynamic from "next/dynamic";

// Dynamic import with SSR disabled for browser-only heavy widget
const HeavyAnalyticsChart = dynamic(
  () => import("@/components/HeavyAnalyticsChart"),
  {
    loading: () => <div className="skeleton-chart" />,
    ssr: false,
  }
);

export function DashboardPage() {
  return (
    <main>
      <HeroHeader />
      <Suspense fallback={<div className="skeleton" />}>
        <HeavyAnalyticsChart />
      </Suspense>
    </main>
  );
}

3. Replacing Heavy npm Packages with Lightweight Alternatives

Replacing legacy npm packages with modern, tree-shakeable equivalents reduces bundle sizes drastically:

Heavy PackageSizeModern AlternativeSizeSaved
moment.js280 kBdate-fns / native Intl2-8 kB~97%
lodash70 kBlodash-es / native ES20241-4 kB~95%
axios32 kBNative fetch()0 kB100%

4. Key Metrics to Target

  • LCP Target: Under 1.8s on 4G mobile networks.
  • Initial JS Bundle: Under 100 kB gzipped for the critical initial chunk.
  • CLS (Cumulative Layout Shift): 0.00 by reserving explicit width and height dimensions on images and dynamic containers.

5. A Release Checklist

  • Confirm the actual LCP element in a trace; optimize that element first.
  • Serve responsive images in modern formats instead of shipping a desktop-sized hero to a phone.
  • Test a cold load on a throttled mobile profile and a warm navigation separately.
  • Recheck real-user p75 LCP after deployment. A lab improvement matters only when field data agrees.