DEV Community

Cover image for Optimasi Font Arab Web: Studi Kasus Core Web Vitals pada Teks RTL
Mightyblue
Mightyblue

Posted on

Optimasi Font Arab Web: Studi Kasus Core Web Vitals pada Teks RTL

Situs kajian keislaman punya masalah yang jarang dibahas di blog teknis manapun: hampir setiap paragraf mengandung kutipan ayat, hadits, dan istilah Arab bertanda harakat. Bukan satu-dua kata. Bisa 30% dari total karakter halaman.

Dan font Arab itu berat. Sangat berat.

Data dari Web Almanac 2025 milik HTTP Archive mencatat bahwa dukungan skrip Arab hanya ada di sekitar 0,7% font desktop dan 0,9% font mobile — angka yang kecil, tapi menyimpan konsekuensi performa yang besar bagi siapa pun yang menggarapnya. Di sinilah optimasi font Arab web berhenti jadi urusan estetika dan mulai jadi urusan Core Web Vitals.

Selama beberapa bulan terakhir saya menangani sisi teknis Kajian Nida Al-Islam, sebuah situs majelis ta'lim di Cilamaya, Karawang, yang memuat ratusan artikel Aqidah, Hadits, Fiqh, dan Sirah. Landasan teknisnya saya ambil dari dokumentasi best practices fonts di web.dev, yang menjelaskan trade-off antara font-display, layout shift, dan kecepatan render — sesuatu yang berperilaku sangat berbeda ketika yang dirender adalah teks RTL bertanda diakritik.

Kenapa tema ini layak diangkat? Karena mayoritas tutorial performa web menganggap dunia ini hanya berisi Latin.

Padahal ada ribuan situs berbahasa Arab, Persia, Urdu, dan Ibrani yang gagal lolos Core Web Vitals bukan karena developernya malas, tapi karena tidak ada dokumentasi yang membahas kasus mereka. Artikel ini mengisi celah itu.


"Fonts are not decoration. They are render-blocking resources that happen to look pretty."
— Prinsip yang saya pegang setelah tiga kali gagal memperbaiki CLS dengan cara yang salah.


1. Kenapa Font Arab Menghancurkan Core Web Vitals

Sebelum masuk ke solusi, penting memahami bahwa masalahnya bukan tunggal. Ada tiga lapisan yang saling menumpuk, dan memperbaiki satu tanpa yang lain hanya memindahkan masalah.

Ukuran File yang Tidak Masuk Akal

Font Latin standar berisi sekitar 200–400 glyph. Font Arab yang layak pakai? Bisa menembus 1.500+ glyph.

Alasannya struktural. Setiap huruf Arab punya empat bentuk kontekstual: isolated, initial, medial, dan final. Belum termasuk ligatur wajib seperti lam-alif, plus tanda harakat (fathah, kasrah, dhammah, sukun, tasydid) yang masing-masing adalah glyph terpisah.

Hasilnya: file WOFF2 font Arab kualitas bagus sering berada di kisaran 180–350 KB. Bandingkan dengan Inter Latin subset yang bisa ditekan sampai 15 KB.

Metrik Vertikal yang Liar

Ini penyebab CLS yang paling sering terlewat.

Huruf Arab punya ascender dan descender yang jauh lebih ekstrem daripada Latin. Ketika browser menampilkan fallback font dulu lalu menukarnya dengan webfont, tinggi baris berubah drastis — dan seluruh halaman bergeser.

Fallback System Font yang Tidak Konsisten

Android, iOS, Windows, dan macOS masing-masing punya font Arab default yang berbeda dengan metrik berbeda pula. Artinya perilaku fallback Anda tidak bisa diprediksi lintas perangkat.

Aspek Font Latin (Inter) Font Arab (Amiri/Noto Naskh)
Jumlah glyph ~350 1.500+
Ukuran WOFF2 (full) ~45 KB ~280 KB
Ukuran WOFF2 (subset) ~15 KB ~90 KB
Bentuk kontekstual Tidak ada 4 per huruf
Risiko CLS saat swap Rendah Tinggi
Konsistensi fallback OS Baik Buruk

2. Diagnosis: Mengukur Sebelum Menebak

Kesalahan pertama saya adalah langsung menambal. Ganti font-display, tambah preload, berharap skor naik. Tidak naik. Karena saya belum tahu mana yang sebenarnya rusak.

Memisahkan LCP dari CLS

Lighthouse akan memberi Anda satu skor gabungan yang menyesatkan. Yang perlu dipisah:

  • LCP terhambat → masalahnya ukuran file dan urutan request
  • CLS tinggi → masalahnya metrik vertikal dan strategi swap
  • INP buruk → biasanya bukan font, cek dulu sebelum menyalahkan tipografi

Merekam Layout Shift Secara Nyata

Jalankan ini di console pada koneksi yang di-throttle ke Slow 3G:

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log('CLS:', entry.value, entry.sources);
    }
  }
}).observe({ type: 'layout-shift', buffered: true });
Enter fullscreen mode Exit fullscreen mode

Properti entry.sources inilah yang berharga. Dia menunjuk elemen DOM persis mana yang bergeser — dan dalam kasus saya, 80% shift berasal dari blok <blockquote> berisi kutipan ayat.

Untuk kerangka audit yang lebih umum sebelum masuk ke kasus RTL, checklist performa web font dari Jakub Andrzejewski — Google Developer Expert di bidang Web Performance — adalah titik awal yang solid. Artikel ini melengkapi checklist tersebut untuk skrip non-Latin.


3. Subsetting: Memotong Tanpa Merusak Makna

Di sinilah optimasi font Arab web berbeda tajam dari optimasi font Latin. Subsetting Latin itu aman — buang Cyrillic, buang Greek, selesai. Subsetting Arab bisa merusak teks secara fatal jika salah potong.

Aturan yang Tidak Boleh Dilanggar

Jangan pernah subset berdasarkan daftar karakter yang muncul di teks Anda saja. Anda akan kehilangan bentuk kontekstual, dan huruf-huruf akan berdiri sendiri tanpa tersambung — pembaca Arab akan langsung tahu ada yang salah.

Yang benar: subset berdasarkan Unicode range, dan pertahankan seluruh tabel GSUB/GPOS.

Konfigurasi Subsetting yang Aman

pyftsubset AmiriQuran.ttf \
  --unicodes="U+0600-06FF,U+0750-077F,U+FB50-FDFF,U+FE70-FEFF" \
  --layout-features="init,medi,fina,isol,liga,rlig,calt,mark,mkmk" \
  --flavor=woff2 \
  --output-file=amiri-subset.woff2
Enter fullscreen mode Exit fullscreen mode

Perhatikan --layout-features. Fitur mark dan mkmk mengatur posisi harakat di atas dan bawah huruf. Buang keduanya, dan tanda baca akan melayang di posisi acak.

Hasil di situs saya: dari 287 KB turun ke 94 KB. Turun 67%, tanpa satu pun glyph rusak.

Memisahkan Font Teks dan Font Kutipan

Strategi yang akhirnya paling efektif: dua font terpisah.

  • Font body — subset minimal, hanya Arabic Presentation Forms yang umum, tanpa harakat lengkap. Untuk istilah teknis di tengah paragraf.
  • Font kutipan — lengkap dengan seluruh tanda tajwid, dimuat lazy dan hanya di halaman yang memuat ayat.

Halaman indeks kategori jadi tidak perlu memuat font berat sama sekali.


4. Menaklukkan CLS dengan Metric Override

Ini bagian yang mengubah segalanya. Dan ini juga bagian yang paling sedikit didokumentasikan untuk skrip Arab.

Konsep size-adjust

Alih-alih menghindari swap, kita membuat fallback font meniru metrik webfont sedekat mungkin. Kalau tinggi barisnya identik, swap tidak menghasilkan pergeseran.

@font-face {
  font-family: 'Amiri Fallback';
  src: local('Noto Naskh Arabic'), local('Geeza Pro'), local('Tahoma');
  size-adjust: 108%;
  ascent-override: 92%;
  descent-override: 38%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Amiri';
  src: url('/fonts/amiri-subset.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+FB50-FDFF, U+FE70-FEFF;
}

.arabic-text {
  font-family: 'Amiri', 'Amiri Fallback', serif;
  direction: rtl;
  text-align: right;
}
Enter fullscreen mode Exit fullscreen mode

Nilai size-adjust dan ascent-override di atas bukan angka ajaib. Anda harus mengukurnya sendiri untuk pasangan font Anda.

Cara Menghitung Nilai Override

  1. Render satu paragraf uji dengan webfont, ukur tinggi elemen via getBoundingClientRect()
  2. Render paragraf identik dengan fallback saja, ukur lagi
  3. size-adjust = (tinggi webfont ÷ tinggi fallback) × 100%
  4. Ulangi untuk ascent-override menggunakan baseline offset
  5. Verifikasi dengan PerformanceObserver — target CLS di bawah 0,05

Di situs kajian, CLS turun dari 0,31 ke 0,02 hanya dari langkah ini. Tanpa mengubah satu byte pun ukuran font.


5. Urutan Loading yang Benar

Subset sudah ringan, CLS sudah aman. Tersisa LCP.

Preload Selektif, Bukan Preload Semua

Kesalahan umum: preload semua font sekaligus. Yang terjadi, font-font itu berebut bandwidth dengan gambar LCP Anda.

<link rel="preload" 
      href="/fonts/amiri-body-subset.woff2" 
      as="font" 
      type="font/woff2" 
      crossorigin>
Enter fullscreen mode Exit fullscreen mode

Satu font saja. Yang benar-benar muncul di viewport pertama.

Memuat Font Kutipan Secara Kondisional

const quoteBlocks = document.querySelectorAll('.ayat-quote');

if (quoteBlocks.length > 0) {
  const quoteFont = new FontFace(
    'AmiriQuran',
    'url(/fonts/amiri-quran-subset.woff2)',
    { display: 'swap', unicodeRange: 'U+0600-06FF, U+FE70-FEFF' }
  );

  const observer = new IntersectionObserver((entries) => {
    if (entries.some(e => e.isIntersecting)) {
      quoteFont.load().then(f => document.fonts.add(f));
      observer.disconnect();
    }
  }, { rootMargin: '300px' });

  observer.observe(quoteBlocks[0]);
}
Enter fullscreen mode Exit fullscreen mode

Font berat baru diambil ketika blok kutipan mendekati viewport. Pada artikel panjang, ini sering berarti font tersebut tidak pernah dimuat sama sekali bagi pembaca yang hanya membaca pembuka.

Cache Header yang Agresif

Cache-Control: public, max-age=31536000, immutable
Enter fullscreen mode Exit fullscreen mode

Font tidak pernah berubah. Beri nama dengan hash, cache selamanya.


6. Panduan Implementasi Langkah demi Langkah

Bab ini merangkum seluruh proses jadi urutan yang bisa Anda ikuti dari nol. Estimasi waktu total sekitar tiga jam untuk situs berukuran sedang.

Langkah 1 — Audit Baseline (20 menit)

Jalankan Lighthouse pada tiga halaman berbeda: beranda, artikel panjang, dan halaman kategori. Catat LCP, CLS, dan total transfer font. Simpan angkanya; Anda butuh pembanding.

Langkah 2 — Inventarisasi Font (15 menit)

Buka DevTools → Network → filter Font. Berapa file yang dimuat? Berapa yang benar-benar terpakai di viewport pertama? Biasanya jawabannya mengejutkan.

Langkah 3 — Subsetting (30 menit)

Install fonttools, jalankan pyftsubset dengan konfigurasi di bab 3. Verifikasi hasilnya dengan membuka file di browser dan membandingkan rendering ayat panjang berdampingan dengan aslinya.

Langkah 4 — Ukur dan Terapkan Metric Override (45 menit)

Ini bagian paling memakan waktu, tapi memberi dampak terbesar pada CLS. Ikuti lima langkah perhitungan di bab 4. Sabar — iterasi dua sampai tiga kali itu normal.

Langkah 5 — Atur Strategi Loading (30 menit)

Preload satu font kritis. Pindahkan font kutipan ke lazy load kondisional. Set cache header.

Langkah 6 — Validasi Lintas Perangkat (40 menit)

Uji minimal di Chrome Android, Safari iOS, dan Firefox desktop. Fallback font Arab berbeda di tiap platform, jadi metric override Anda mungkin butuh sedikit penyesuaian.

Tahap Waktu Dampak Utama Tingkat Kesulitan
Audit baseline 20 mnt Data pembanding Mudah
Inventarisasi font 15 mnt Identifikasi pemborosan Mudah
Subsetting 30 mnt LCP turun signifikan Sedang
Metric override 45 mnt CLS turun drastis Sulit
Strategi loading 30 mnt LCP + hemat bandwidth Sedang
Validasi perangkat 40 mnt Konsistensi lintas OS Sedang

7. Hasil Nyata dan Apa yang Tidak Berhasil

Transparansi soal kegagalan sama pentingnya dengan melaporkan keberhasilan. Berikut angka sebenarnya, termasuk pendekatan yang saya buang.

Yang Berhasil

Metrik Sebelum Sesudah Perubahan
LCP (mobile, Slow 3G) 4,8 s 2,1 s −56%
CLS 0,31 0,02 −94%
Total transfer font 412 KB 118 KB −71%
Lighthouse Performance 47 91 +44 poin

Yang Tidak Berhasil

font-display: optional. Secara teori paling aman untuk CLS. Praktiknya, pada koneksi lambat font tidak pernah muncul sama sekali — dan pembaca melihat ayat dalam font sistem yang harakatnya berantakan. Untuk konten keagamaan, ini tidak bisa diterima.

Variable font Arab. Menjanjikan di atas kertas. Ukurannya justru lebih besar daripada dua static subset, karena axis interpolation untuk skrip kompleks menyimpan data yang banyak.

Mengandalkan Google Fonts API. Subset otomatis mereka untuk Arab terlalu konservatif, dan Anda kehilangan kontrol atas unicode-range. Self-host memberi hasil jauh lebih baik.


Pertanyaan yang Sering Muncul

Apakah teknik ini berlaku untuk skrip RTL lain?

Sebagian besar ya. Ibrani dan Persia punya karakteristik serupa, meski Ibrani tidak punya bentuk kontekstual sebanyak Arab sehingga subsetting-nya lebih longgar. Untuk Urdu, hati-hati — gaya Nastaliq punya kebutuhan ligatur yang jauh lebih kompleks dan subsetting agresif berisiko merusaknya.

Berapa target CLS yang realistis untuk situs Arab?

Di bawah 0,1 adalah ambang "Good" menurut Google, dan itu sepenuhnya bisa dicapai. Di bawah 0,05 realistis jika metric override Anda dihitung dengan benar.

Apakah harakat wajib disertakan?

Tergantung konten. Untuk kutipan Al-Qur'an dan hadits, wajib — menghilangkannya mengubah bacaan. Untuk istilah teknis dalam paragraf Indonesia, biasanya tidak perlu, dan ini peluang penghematan besar.

Bagaimana menangani teks campuran Arab-Latin dalam satu paragraf?

Gunakan unicode-range untuk memisahkan font per rentang karakter, dan bungkus segmen Arab dengan <span dir="rtl">. Browser akan otomatis memilih font yang tepat per karakter tanpa memuat font yang tidak diperlukan.

Apakah size-adjust didukung semua browser?

Chrome, Edge, Firefox, dan Safari modern sudah mendukungnya. Browser lama akan mengabaikan properti tersebut dan kembali ke perilaku swap biasa — degradasi yang aman, bukan kerusakan.

Perlukah CDN khusus font?

Untuk sebagian besar kasus, tidak. Self-host dari origin yang sama menghilangkan DNS lookup tambahan dan koneksi TLS baru, yang sering lebih menguntungkan daripada keunggulan geografis CDN.


Tipografi Adalah Aksesibilitas

Mengakhiri pembahasan ini, ada satu hal yang layak digarisbawahi: pekerjaan optimasi font Arab web sebenarnya bukan pekerjaan performa. Ia pekerjaan aksesibilitas yang kebetulan diukur dengan metrik performa.

Ketika seseorang di Karawang membuka artikel kajian lewat jaringan yang tidak stabil, lalu menunggu empat detik hanya untuk melihat teks Arab yang harakatnya bergeser-geser — yang hilang bukan sekadar skor Lighthouse. Yang hilang adalah akses terhadap ilmu.

Soal ini pernah diperjuangkan lama sebelum Core Web Vitals ada. Håkon Wium Lie, pencetus konsep CSS di CERN pada 1994 bersama Tim Berners-Lee dan Robert Cailliau, serta mantan CTO Opera Software, sejak 2006 aktif berkampanye agar browser mendukung downloadable web fonts dengan format terbuka. Alasannya sederhana:

"The web is for everyone, and typography is a fundamental part of how we read. Locking fonts away means locking away languages."

Poin Lie relevan persis di sini. Selama satu-satunya font yang praktis dipakai adalah font sistem berbasis Latin, seluruh bahasa yang menggunakan skrip lain berada di posisi kelas dua di web. Webfont membuka pintu itu. Tapi membuka pintu saja tidak cukup — kalau pintunya berat dan macet, orang tetap tidak masuk.

Di situlah pekerjaan kita sebagai developer dimulai. Subsetting yang cermat, metric override yang dihitung, loading yang selektif. Bukan agar angka di dashboard terlihat hijau, tapi agar teks yang ingin dibaca orang benar-benar sampai ke mata mereka.

Kalau Anda menggarap situs dengan skrip non-Latin, saya ingin dengar pengalaman Anda di kolom komentar. Terutama kegagalan-kegagalannya — bagian itu yang paling jarang ditulis orang.


Ditulis berdasarkan pengerjaan teknis situs Kajian Nida Al-Islam, majelis ta'lim di Cilamaya, Karawang, yang memuat materi Aqidah, Manhaj, Hadits, Fiqh, Tafsir, dan Sirah Nabawiyah.

Top comments (0)