- Ini adalah eksperimen untuk mengurangi jumlah data yang ditransfer ketika GitHub Pages tidak mendukung Brotli, dengan mengenkode HTML sebagai gambar WebP lossless lalu memulihkannya menggunakan image decoder browser dan JavaScript
- Decoder WASM Brotli membutuhkan biaya tambahan
71 KiB~200 KB, sementara Compression Streams API hanya mendukunggzip,deflate, dandeflate-raw, sehingga sulit menjadi jalan pintas untuk decoding Brotli - VP8L WebP lossless dapat menghasilkan ukuran lebih kecil daripada gzip bahkan untuk data yang bersifat teks, berkat predictive transform, penggunaan ulang Huffman tree per blok 16x16, dan color cache
- HTML uji
439,478byte menyusut menjadi gzip94,683byte dan WebP43,182byte; masih lebih besar daripada Brotli37 KiB, tetapi sekitar 2,2 kali lebih kecil dibanding gzip - Karena noise anti-fingerprinting pada Canvas 2D, perubahan WebGL
readPixels, layar kosong awal, dan masalah pemulihan scroll, ini lebih dekat ke hack yang mengungkap batasan browser daripada sesuatu yang layak diterapkan sungguhan
Masalah tidak bisa memakai Brotli di GitHub Pages
- Saat mengurangi waktu muat halaman, kompresi HTTP memberi efek lebih besar daripada minify HTML
- HTTP mendukung gzip dan Brotli melalui header
Content-Encoding- gzip murah sehingga biasanya aktif secara default
- Brotli umumnya memiliki rasio kompresi lebih baik daripada gzip, tetapi jauh lebih lambat
- GitHub Pages tidak mendukung Brotli, sehingga tulisan terpanjang di situs,
Recovering garbled Bitcoin addresses, menjadi92 KiBdengan gzip, padahal bisa37 KiBjika memakai Brotli - Karena perbedaan ini, waktu muat menjadi 2,5 kali lebih lama secara tidak perlu
Alternatif pertama yang terpikir dan titik buntu
- Jika GitHub mendukung unggah dan penyajian file Brotli yang sudah dikompresi sebelumnya, masalah ini bisa dihindari, tetapi fitur seperti itu tidak disediakan
- Opsi melakukan dekompresi langsung di sisi klien dengan JavaScript kehilangan keunggulannya karena ukuran decoder WASM
- brotli-dec-wasm sekitar
200 KB - tiny-brotli-dec-wasm berukuran
71 KiB - Perbandingannya menjadi gzip
92 KiBversus isi Brotli37 KiB + 71 KiB, sehingga manfaatnya hilang
- brotli-dec-wasm sekitar
- Stack HTTP browser memiliki decoder Brotli, tetapi DecompressionStream dari Compression Streams API hanya menerima
gzip,deflate, dandeflate-raw - Walaupun
gzipdikompresi sebelumnya dengan Zopfli, hasilnya86 KiB, tetap lebih besar daripada Brotli
Memakai format gambar seperti container kompresi
- Browser dapat mendecode gambar, jadi jika data dimasukkan ke piksel gambar lalu dibaca kembali dengan Canvas API, tidak perlu menambahkan logika dekompresi baru
- GIF membentangkan data dalam urutan row-major lalu menerapkan LZW, tetapi sulit mengharapkan keuntungan karena DEFLATE pada gzip dirancang untuk menggantikan LZW
- PNG memakai DEFLATE, tetapi lebih dulu menerapkan predictive transform yang mengompresi selisih terhadap piksel tetangga, bukan sumber piksel mentah
- Contoh: mengompresi
[a, b, c, d]bukan sebagai itu, melainkan[a, b-a, c-b, d-c] - Semakin kecil selisih antara nilai prediksi dan nilai sebenarnya, semakin menguntungkan untuk kompresi Huffman
- Contoh: mengompresi
- Inti eksperimen ini adalah memanfaatkan VP8L, yaitu WebP lossless, untuk kompresi data byte umum
Perbedaan VP8L dengan gzip
- WebP memiliki varian lossy dan lossless; di sini hanya dibahas VP8L, format lossless
- VP8L memakai predictive transform seperti PNG, tetapi alih-alih DEFLATE, ia memakai metode mirip DEFLATE buatan Google
- DEFLATE dapat membagi file menjadi beberapa potongan dan menaruh Huffman tree yang sesuai untuk tiap potongan
- Jika JavaScript, SVG, dan markup bercampur dalam satu HTML, tree yang berbeda dapat lebih menguntungkan
- VP8L mendefinisikan tabel Huffman tree yang ukurannya dapat dibuat sangat besar, lalu tiap blok piksel 16x16 dapat memakai tree berbeda
- Jika setelah JavaScript muncul CSS lalu JavaScript lagi, DEFLATE dapat mengenkode tree yang mirip berkali-kali
- VP8L dapat menggunakan ulang tree, sehingga bisa mengganti tree lebih sering dan lebih murah
- Color cache VP8L dapat merepresentasikan nilai secara singkat, misalnya dengan instruksi untuk menyalin piksel terbaru yang memiliki atribut tertentu
Eksperimen kompresi WebP pertama
- File uji adalah HTML
Recovering garbled Bitcoin addresses- Ukuran asli:
439,478byte gzip --best:94,683byte
- Ukuran asli:
- Dengan crate webp di Rust, byte diubah menjadi gambar RGB grayscale lalu dikompresi menjadi WebP lossless
- Alasan memakai grayscale adalah transform
subtract greenpada WebP- Pada grayscale, jika kanal G dikurangkan dari R/B, R/B pada dasarnya menjadi 0
- Karena WebP mengenkode tiga kanal dengan Huffman tree terpisah, kanal bernilai tetap mendekati ruang
O(1)
- Awalnya gambar hendak dibuat sebagai
1xN, tetapi WebP hanya mendukung maksimum16383x16383, sehingga muncul errorVP8_ENC_ERROR_BAD_DIMENSION - Setelah disesuaikan menjadi bentuk
16383xN, hasilnya45,604byte, 2 kali lebih kecil daripada gzip dan bahkan lebih kecil daripada bzip249,764byte
Penyesuaian khusus WebP
- Jika gambar lebar memakai urutan row-major, byte yang berjauhan dalam input bercampur dalam blok 16x16
- Mengubah bentuk gambar menjadi tinggi dan sempit,
27x16383, menurunkan hasil kompresi menjadi43,232byte - Pengaturan performa kompresi
cwebp, yaitu method, dibandingkan dari0~6- method 0:
48,902 - method 1:
43,546 - method 2:
43,442 - method 3:
43,292 - method 4:
43,232 - method 5:
43,182 - method 6:
43,182
- method 0:
- method
5dipilih sebagai opsi yang lebih cepat sambil menghasilkan ukuran yang sama dengan method6 - Dalam keadaan ini, WebP 2,2 kali lebih kecil daripada gzip dan 1,2 kali lebih besar daripada Brotli
Benchmark beberapa file
- Objek perbandingan adalah snappy testdata, Canterbury Corpus dan Large Corpus, serta 2 file SVG
- Format yang dibandingkan adalah
gzip --best,brotli --best,bzip2 --best, dan skrip kompresi WebP - WebP hampir selalu lebih baik daripada gzip, kecuali file yang sangat kecil seperti
grammar.lsp,xargs.1, dan beberapa pengecualian - Pengecualiannya adalah
kennedy.xlsdanpaper-100k.pdfpaper-100k.pdfmemiliki data terkompresi setelah XML19 KB, sehingga pada dasarnya situasinya seperti mengukur data kecil- Performa relatif Brotli/bzip2 pada
kennedy.xlsjuga aneh, dan bisa jadi ini file dengan banyak data heterogen di lokasi berdekatan sehingga sulit ditangani kompresor
- WebP cenderung sedikit lebih buruk daripada bzip2, tetapi dalam beberapa kasus mengunggulinya
- WebP selalu lebih buruk daripada Brotli, kecuali pengecualian yang hampir menyerupai blob acak seragam seperti
fireworks.jpeg - Pada data plain-text besar, WebP menghasilkan peningkatan yang terukur dibanding gzip
- Ada peningkatan juga pada file SVG
- Pada
html_x_4, WebP mencatat rasio kompresi3,3%; masih lebih buruk daripada Brotli2,8%, tetapi jauh lebih baik daripada gzip13%
Memulihkan dengan JavaScript
- Decoding WebP sendiri dapat diimplementasikan dengan
fetch,createImageBitmap,OffscreenCanvas,getImageData, danTextDecoder - Strukturnya memakai kanal R piksel sebagai byte HTML asli, mendecodenya sebagai UTF-8, lalu memasukkannya ke
document.documentElement.innerHTML - Karena Canvas API sering dipakai untuk fingerprinting, sebagian browser menambahkan noise pada hasil
getImageData- Pada strict tracking protection di Firefox, kurang dari 1% piksel dapat terdampak
- Dalam HTML, noise ini muncul seperti typo
- Jika memakai
readPixelsdari WebGL, saat itu dapat berjalan tanpa noise- WebGL hanya mendukung tekstur secara stabil hingga
2048x2048, sehingga batas ukuran harus disesuaikan lagi - Kode pemulihan ini sekitar
550byte setelah minify
- WebGL hanya mendukung tekstur secara stabil hingga
- Jika WebP dan kode digabung, ukurannya menjadi
44 KiB, dibandingkan dengan gzip92 KiBdan Brotli37 KiB - Setelah 15 April 2026, Firefox menambahkan anti-fingerprinting juga pada
readPixels, sehingga cara ini tidak lagi bekerja apa adanya
Kedipan layar dan masalah scroll
- Karena
awaitdiproses berbasis promise, browser menganggap eksekusi skrip sudah selesai sebelum unduhan WebP selesai - DOM masih kosong, sehingga pengguna melihat layar putih kosong sebentar
- Sebagai mitigasi, style dan sekitar
8 KiBbagian atas halaman dapat tetap berada di HTML gzip, sementara hanya konten di bawah viewport yang dikompresi sebagai WebP - Pemulihan posisi scroll saat refresh juga menjadi masalah
- Misalnya, jika refresh dilakukan pada posisi
Y = 5000pxtetapi tinggi halaman0px, posisi akan direset - Menambahkan
divsementara yang sangat besar dapat membantu
- Misalnya, jika refresh dilakukan pada posisi
- Agar dokumen saat ini dapat diperbarui tanpa diganti menjadi dokumen baru, harus menetapkan
document.documentElement.innerHTML, bukan memakaidocument.write
Memasukkan WebP langsung ke JavaScript
- Untuk sedikit mengurangi latensi, WebP dapat di-embed langsung di dalam JavaScript
- Cara paling sederhana adalah base64 data URL
- base64 memperbesar ukuran asli menjadi
1,33 kali, tetapi gzip hampir sepenuhnya meniadakan kenaikan ini- Jika
compressed.webpdijadikan base64, ukurannya57,576byte - Jika ini dikompresi dengan gzip
--best, hasilnya43,519byte
- Jika
- Blob terkompresi seperti WebP hampir berupa data acak seragam, dan terhadap hasil konversi 8-bit-ke-6-bit base64, Huffman tree milik gzip pada dasarnya bekerja seperti transformasi balik
- Unicode dan UTF-16 juga bisa digunakan, tetapi base64 tetap menjadi solusi awal yang memadai
Penerapan nyata dan kondisi setelahnya
- Pada saat tulisan ini dibuat, halaman ini sendiri dikompresi dengan WebP mulai dari bagian “Fool me twice”, kecuali di browser lama atau lingkungan dengan JavaScript nonaktif
- Gambar WebP pada halaman sebenarnya tinggi dan sempit dalam kode sungguhan, tetapi contoh WebP berbentuk persegi juga disediakan agar enak dilihat
- Dalam gambar, bagian atas dan bawah yang terang adalah teks dan kode, area bergaris sekitar 1/5 dari atas adalah diagram, dan sebagian besar area gelap adalah teks di dalam diagram
- Penghematan sebenarnya terbatas
- Halaman gzip lama:
88 KiB - Halaman gzip setelah menerapkan WebP:
83 KiB - Perkiraan Brotli:
69 KiB
- Halaman gzip lama:
- Setelah 15 April 2026, agar pengunjung Firefox tidak melihat konten rusak, saat ini halaman diubah kembali menjadi halaman tanpa kompresi
- Kode Rust, korpus, dan file lainnya tersedia di GitHub
1 komentar
Pendapat Hacker News
Mungkin benar kalau mengabaikan latensi, tetapi dalam praktiknya waktu muat tampaknya hanya bertambah sekitar 0,001%
Kenaikan ukuran itu tidak berarti dibanding latensi bolak-balik, dan waktu yang dihabiskan untuk dekompresi bisa saja lebih besar daripada waktu yang dihemat dengan mengirim 55KiB lebih sedikit
Meski ini eksperimen yang menarik, dalam kasus ini pengalaman pengguna kemungkinan besar justru memburuk, dan kecepatannya hampir sama sementara kompatibilitasnya saja yang menurun
Masalahnya, ada orang seperti penulis TFA yang berusaha mengecilkan 100KB menjadi 50KB, tetapi ada juga tempat yang tanpa pikir panjang mengirim puluhan MB gambar kepada saya saat saya hanya ingin melihat jam buka restoran lewat data roaming
Kesadaran terhadap sumber daya memang ada, tetapi sayangnya penyebarannya sangat tidak merata
Jika koneksi terputus, semuanya hilang, dan bahkan bagian yang sudah diunduh pun tidak bisa dibaca
Pada koneksi normal perbedaannya tidak berarti, dan pada koneksi yang sangat lambat atau tidak stabil sampai 50KB jadi penting, cara ini jelas lebih buruk. Eksperimen yang menarik, tetapi saya berharap ini tidak diterapkan di situs
Symbols-2048-em%20Nerd%20Font%20Complete.woff2berukuran 850K, jadi perbedaannya hampir tertutup olehnyaMemang tidak sampai 2,5 kali berbeda, tetapi juga bukan 0,001%
Pada jaringan yang mengalami loss mungkin bisa berbeda, tetapi saya tidak yakin
Saya tidak tahu kenapa
readPixelsbukan target perlindungan fingerprinting. Bagi saya tidak masalah, karena saya tidak menyebarkan typo yang nyaris tak terlihat ke seluruh halamanBagian yang mengatakan bahwa HTML yang di-gzip hanya berisi style dan sekitar 8KiB bagian atas halaman, sementara konten di bawah viewport saja yang dikompresi sebagai WebP, menjelaskan mengapa artikel tiba-tiba terputus setelah kalimat acak lalu diikuti halaman kosong
Saya memakai LibreWolf, jadi WebGL dimatikan, dan untuk game web acak yang membutuhkan WebGL saya memakai Chromium. Saat WebGL dinyalakan, artikelnya berjalan dengan baik, dan jujur tekniknya cukup rapi
WWW semestinya dapat diakses secara universal dengan cara yang dimulai dari HTML biasa lalu ditingkatkan secara progresif
Menggunakan Brotli secara langsung di browser web memang memungkinkan, tetapi tentu ada batasannya
Saya rasa karya kiriman JS1024 tahun 2022 [1] adalah demonstrasi pertama konsep ini, dan ada juga kode proof-of-concept untuk kompresi arbitrer. Sayangnya, itu tidak cocok untuk size coding yang merupakan tujuan awalnya
Batasan utamanya adalah pada dasarnya terbatas pada karakter ASCII, dan karena alasan yang jelas sangat sensitif terhadap stack rendering. Saat ini tampaknya tidak berjalan di Firefox
[1] https://js1024.fun/demos/2022/18/readme
[2] https://gist.github.com/lifthrasiir/1c7f9c5a421ad39c1af19a9c...
Yang bisa digunakan hanyalah format file font WOFF2, yang memang menjadi tujuan awal desain Brotli, tetapi untuk memanfaatkannya kita harus membuat seluruh file font
Browser modern biasanya membersihkan font dengan OpenType Sanitizer (OTS), karena memasukkan file font tidak tepercaya langsung ke sistem sangat berbahaya. Jadi kita harus membuat file WOFF2 yang cukup normal agar diterima OTS, tetapi tetap memuat rangkaian byte yang diinginkan di dalamnya dan bisa diekstrak
Setelah banyak kegagalan, gagasan untuk akhirnya memakai lebar glyph, yaitu advance, yang dienkode sebagai deret integer bertanda 2 byte nyaris tanpa batasan itu benar-benar fantastis
Pihak Chromium sudah lama memblokirnya, tetapi zstd sekarang juga mulai masuk ke web. Karena akhirnya sudah masuk Chrome, tinggal Safari saja yang perlu menyusul
Saya sedang membuat Batch Compress(https://batchcompress.com/en), dan belum lama setelah menambahkan dukungan WebP, saya mengubahnya menjadi default
Sepengetahuan saya, alat ini sudah menghasilkan JPEG terkecil di antara alat kompresi web, tetapi WebP hanya berukuran sekitar 50% dari JPEG. Setelah dukungannya ditambahkan, menjadikannya default adalah keputusan yang mudah
Karena situs ini punya cukup banyak pengguna, saya sempat mengira akan ada beberapa keluhan setelah WebP dijadikan default, tetapi sekarang, sekitar sebulan kemudian, hanya ada satu pertanyaan atau keluhan terkait WebP
Sepertinya sekarang hampir semua alat dan browser sudah mendukung WebP. Baru-baru ini saya hanya melihat satu situs web yang langkah berikutnya terhambat karena tidak bisa menangani unggahan gambar WebP dengan benar; selebihnya sekarang hampir semuanya mendukungnya dengan baik
Jika JPEG dikompresi dan dioptimalkan dengan baik, seharusnya tidak tertinggal jauh dari WebP
Anda memang selalu bisa membuat WebP yang tampak hampir sama dengan JPEG lalu mengurangi ukuran file, tetapi hal yang sama juga berlaku jika mengompres ulangnya menjadi JPEG yang tampak hampir sama
Ini adalah sifat semua codec kompresi lossy, dan karena ukuran file meningkat secara eksponensial seiring naiknya kualitas, orang selalu terkejut bahwa penurunan kualitas yang sangat kecil dan nyaris tak terlihat saja bisa membuat ukuran file berbeda jauh
WebP dulu terkenal buruk karena default-nya yang mengacaukan detail di area gelap
Saat melihat-lihat sumbernya, saya melihat ada spasi yang hilang pada deklarasi doctype. Bentuk saat ini salah, dan seharusnya ada spasi
Menghilangkan spasi pada
DOCTYPEbisa membuatnya lebih pendekSecara ketat, itu bukan HTML yang valid, tetapi tetap berhasil memicu mode standar
Referensi: https://GitHub.com/kangax/html-minifier/pull/970 / https://HTML.spec.WHATWG.org/multipage/parsing.html#parse-er...
Saya juga memakai trik itu di https://FreeSolitaire.win
Sepertinya itu hasil dari minifier yang menghapus sebanyak mungkin [0]
0: https://github.com/KTibow/KTibow/issues/3#issuecomment-23367...
Saya pernah mencoba trik ini dulu. Anehnya saya tidak ingat dipakai untuk apa, tapi mungkin saat itu hanya ingin melihat apakah bisa, dan saya juga meninggalkan komentar di sini: https://gist.github.com/gasman/2560551?permalink_comment_id=...
Saya juga menemukan prototipe lama, sepertinya hanya tes: https://retr0.id/stuff/bee_movie.webp.html
Sekarang hal seperti injeksi skrip disebut ekstensi, bukan add-on, tetapi bagaimanapun pendekatan awalnya menarik: mengirim “sampah”, lalu menempelkan JS di belakangnya dan mengembalikannya ke halaman
Sisi penggila keamanan dalam diri saya jadi bertanya-tanya apakah serangan bisa dimungkinkan saat ada data yang diberikan pengguna, seperti form komentar
Mungkin saja seseorang menemukan urutan byte untuk dimasukkan ke komentar, lalu setelah dikompresi berubah menjadi tag
scriptyang berada sebelum skrip saya dan dieksekusiSebagian besar hal yang ditambahkan WebP lossless di atas PNG berkaitan dengan pemodelan, bukan encoding, sedangkan kompresi teks seperti ini hanya memakai bagian encoding dari WebP
Menghapus Google Fonts juga akan sedikit memperbaiki waktu muat halaman, karena dimuat dari server jarak jauh dan membutuhkan handshake tambahan
Halaman ini rusak setidaknya di browser Sailfish OS. Ada ruang kosong panjang setelah paragraf berikut
“Alright, so we’re dealing with 92 KiB for gzip vs 37 + 71 KiB for Brotli. Umm…”
Meski begitu, overhead kompresi HTML gzip dan Brotli tidak ada apa-apanya dibanding jumlah JS, gambar, dan video yang dipakai situs web masa kini
Secara pribadi saya kurang suka format ini. Saat menyimpan gambar dan tersimpan sebagai WebP, hampir tidak ada yang mendukungnya selain browser web, jadi harus dikonversi dulu sebelum bisa diedit atau dipakai secara bermakna
Rasanya seperti dipaksa melakukan satu langkah tambahan saja
Namun kalau dukungannya makin luas, sepertinya tidak apa-apa. Format baru sekali tiap 20 tahun masih bisa ditoleransi
.webmboleh saja menghilang