IT
🚀

Praktik Peningkatan Core Web Vitals — Cara Mengurangi LCP dari 3 Detik ke 1.2 Detik

USD/JPY分散は、為替急変局面で一方通貨の過大シェアを防ぎ、月次の再バランスと上限規則で感情的な一括投資を抑える実践設計です。

Praktik Peningkatan Core Web Vitals — Cara Mengurangi LCP dari 3 Detik ke 1.2 Detik

Ringkasan Utama

  • LCP (Largest Contentful Paint) adalah indikator kunci yang secara langsung mempengaruhi peringkat pencarian Google.
  • Dengan menerapkan optimasi gambar, strategi pemuatan font, dan pemisahan kode secara berurutan, LCP berhasil dipangkas dari 3.0 detik menjadi 1.2 detik.
  • CLS menurunkan perubahan layout dari 0.28 menjadi 0.04 dengan menentukan ukuran eksplisit untuk area gambar dan iklan serta menghilangkan perubahan layout.
  • Ini berdasarkan proyek Next.js di produksi, dan prinsip yang sama dapat diterapkan pada proyek React dan Vue.

Pendahuluan — Mengapa Core Web Vitals?

monitor screengrab seo analytics seo analytics

Pada tahun 2021, Google merilis pembaruan Page Experience, menjadikan Core Web Vitals lebih dari sekadar indikator UX, tetapi juga faktor peringkat SEO. Sejak saat itu, Google terus meningkatkan bobot sinyal ini, dan pada tahun 2024, INP (Interaction to Next Paint) akan sepenuhnya menggantikan FID, sehingga kriteria evaluasi juga berevolusi.

Proyek e-commerce yang saya jalankan mendapatkan skor 38 pada PageSpeed Insights untuk perangkat mobile enam bulan lalu. LCP adalah 3.0 detik, CLS 0.28, dan INP 320ms — ketiga indikator tersebut berada dalam kategori "perlu perbaikan". Saya akan mencatat bagaimana saya mengubah indikator tersebut.


Bagaimana Memahami Tiga Core Web Vitals dengan Cepat?

computer screen bunch data on it

LCP — Kecepatan "kesan pertama" halaman

LCP adalah waktu yang diperlukan untuk merender elemen konten terbesar dalam viewport (biasanya gambar hero atau teks H1). Menurut Google, di bawah 2.5 detik adalah baik, dan di atas 4.0 detik adalah buruk.

Di situs e-commerce, gambar banner hero sering kali menjadi target LCP. Jika gambar ini tidak dimuat tepat waktu, semua optimasi lainnya menjadi tidak berarti.

CLS — Apakah layout "melompat"?

CLS (Cumulative Layout Shift) mengukur seberapa banyak elemen bergerak secara tidak terduga selama pemuatan halaman. Jika banner iklan dimasukkan terlambat atau gambar tanpa ukuran yang ditentukan dimuat terlambat, skornya akan tinggi. Di bawah 0.1 adalah kriteria baik.

INP — Seberapa cepat merespons input pengguna?

INP mengukur penundaan respons untuk semua interaksi seperti klik, ketukan, dan input keyboard. Pada bulan Maret 2024, INP menggantikan FID, dan di bawah 200ms adalah kriteria baik. Semakin berat bundel JavaScript, semakin terhambat thread utama, sehingga INP memburuk.


Diagnosa Masalah — Hasil Pengukuran Awal

close up computer screen blurry background

Mencatat indikator sebelum optimasi adalah titik awal. Saya menggunakan alat berikut secara berurutan:

  1. 1PageSpeed Insights — Menyediakan data lapangan (data pengguna nyata) dan data laboratorium (Lighthouse) secara bersamaan.
  2. 2Chrome DevTools > Tab Kinerja — Memeriksa timeline rendering dan elemen kandidat LCP.
  3. 3WebPageTest — Pengukuran nyata berdasarkan server edge CDN domestik, visualisasi dengan film strip.
  4. 4Vercel Analytics / Sentry — Mengumpulkan Core Web Vitals berdasarkan sesi pengguna nyata.

Hasil diagnosis menunjukkan tiga titik kemacetan.

  • Gambar Hero — 4.2MB JPEG, disisipkan langsung dengan tag tanpa optimasi.
  • Google Fonts — Memuat 3 keluarga font secara sinkron dengan metode @import.
  • Ukuran Bundel — Chunk utama 1.8MB, banyak library yang tidak menerapkan tree shaking.

Tiga Cara Mengurangi LCP dari 3.0 Detik ke 1.2 Detik

Cara 1 — Optimasi Gambar dan Preload

Ini adalah yang paling efektif. Saya mengubah cara pemrosesan gambar hero secara total.

Sebelum

html
<img src="/banner.jpg" alt="Banner Utama" />

Sesudah — Komponen Gambar Next.js + Konversi WebP

jsx
import Image from 'next/image';

<Image
  src="/banner.webp"
  alt="Banner Utama"
  width={1920}
  height={800}
  priority          // Gambar yang menjadi target LCP harus memiliki priority
  quality={80}
  sizes="(max-width: 768px) 100vw, 1920px"
/>

Dengan menambahkan prop priority, Next.js secara otomatis menyisipkan tag untuk gambar tersebut. Setelah konversi ke WebP, ukuran file berkurang dari 4.2MB menjadi sekitar 340KB, atau sekitar 92%.

Jika menggunakan proyek HTML/React murni, Anda dapat menambahkan tag preload langsung di dalam .

html
<link
  rel="preload"
  as="image"
  href="/banner.webp"
  type="image/webp"
/>

Dengan satu langkah ini, LCP turun dari 3.0 detik menjadi 1.8 detik.

Cara 2 — Mengubah Strategi Pemuatan Font

Jika Anda memuat Google Fonts dengan @import, browser akan berhenti untuk mem-parsing CSS dan mengirim permintaan font. Waktu tunggu ini sangat meningkatkan LCP.

Sebelum

html
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap');
</style>

Sesudah — + display=swap + Hosting Sendiri

html
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap"
/>

Lebih jauh lagi, jika menggunakan next/font (Next.js 13+), Anda dapat memproses font dengan hosting sendiri pada waktu build, sehingga permintaan eksternal hilang.

js
// app/layout.js
import { Noto_Sans_KR } from 'next/font/google';

const notoSansKR = Noto_Sans_KR({
  weight: ['400', '700'],
  subsets: ['latin'],
  display: 'swap',
});

Setelah perbaikan font, LCP turun dari 1.8 detik menjadi 1.5 detik.

Cara 3 — Pemisahan Kode dan Optimasi Bundel

Jika ukuran bundel JS utama besar, thread utama browser terjebak dalam parsing dan eksekusi. Selama waktu ini, elemen LCP tidak dirender di layar.

Pisahkan bundel awal dengan import dinamis

jsx
import dynamic from 'next/dynamic';

// Komponen grafik berat yang terletak di bawah scroll
const SalesChart = dynamic(() => import('@/components/SalesChart'), {
  ssr: false,
  loading: () => <div className="chart-skeleton" />, 
});

Hapus library yang tidak perlu dengan analisis bundel

bash
npx @next/bundle-analyzer

Hasil analisis menunjukkan bahwa moment.js (66KB gzip) dan seluruh lodash (70KB gzip) terlibat. Saya mengganti moment dengan fungsi yang diperlukan dari date-fns secara individual, dan mengubah lodash menjadi impor tree shaking dari lodash-es.

js
// Sebelum
import _ from 'lodash';
const result = _.groupBy(data, 'category');

// Sesudah
import { groupBy } from 'lodash-es';
const result = groupBy(data, 'category');

Ukuran bundel utama berkurang dari 1.8MB menjadi 420KB, dan LCP turun dari 1.5 detik menjadi 1.2 detik.


Penyebab utama pergeseran layout adalah dua hal.

1. Gambar tanpa ukuran yang ditentukan

Tentukan width dan height untuk semua tag atau tetap menggunakan CSS untuk mengunci aspect-ratio.

css
.product-image-wrapper {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

2. Banner iklan yang dimasukkan terlambat

Sebelum slot iklan dimuat, saya menyiapkan placeholder dengan tinggi yang sama.

jsx
<div style={{ minHeight: '90px' }}>
  <AdBanner slot="header" />
</div>

Dengan dua langkah ini, CLS turun dari 0.28 menjadi 0.04.


Peningkatan INP — Mengurangi Beban Thread Utama

INP secara alami membaik setelah pengurangan ukuran bundel dari 320ms menjadi 140ms. Selain itu, saya menunda bagian perhitungan berat yang dieksekusi secara sinkron di dalam handler event klik dengan requestIdleCallback.

js
button.addEventListener('click', () => {
  // Pembaruan UI yang segera diperlukan
  setLoading(true);

  // Pemrosesan berat ditunda ke waktu idle
  requestIdleCallback(() => {
    processHeavyData(payload);
  });
});

Perbandingan Sebelum dan Sesudah Optimasi

IndikatorSebelum OptimasiSesudah Optimasi
LCP3.0 detik1.2 detik
CLS0.280.04
INP320ms140ms

🔧 Related Free Tools

Terkait