Bagaimana mengurangi ukuran bundel - strategi kelas satu huruf dalam css-modules

Kami meningkatkan kompresi bundel sebesar 40% dari ukuran file, dengan mengganti hashing standar dengan awalan satu huruf + hash dari path file.

Modul-Css memungkinkan Anda untuk menulis komponen Burung dan Kucing, dengan gaya dalam file dengan nama style.css dan .block yang sama di masing-masing, dan kelas-kelas ini akan berbeda untuk masing-masing komponen ini.

/* Bird / styles.css */
.block { }
.name { }
/* Cat / styles.css */
.block { }
.name { }

Tidak ada yang rumit di sini: webpack hashes setiap kelas dari semua file menggunakan pengaturan "[hash: base64: 8]". Semua kelas akan diganti namanya, dan tautan ditambahkan untuk memahami dari mana kelas itu berasal. Dalam versi dasar majelis, kita akan memiliki file styles.css untuk styles dan styles.js untuk tautan saat bekerja dengan js.

Melanjutkan test case, kami mendapatkan 4 kelas independen dengan nama aneh seperti k3bvEft8:

/* Bird */
.k3bvEft8 { }
.f2tp3lA9 { }
/* Cat */
.epIUQ_6W { }
.oRzvA1Gb { }

Jalankan unit produksi dan kompres file. Di stand, file css 300Kb dikemas dalam 70Kb menggunakan gzip [atau 50Kb menggunakan brotli]. Kompresi kecil karena hash adalah string yang dihasilkan secara acak yang kompresnya sangat buruk. Algoritma kompresi tidak melihat urutan dan dipaksa untuk mengingat lokasi masing-masing simbol, mis. mentransfer isi bagian ini sebagaimana adanya, tanpa kompresi.

Sesuatu harus dilakukan dengan ini. Tapi apa? Selama operasi, webpack membaca pohon file secara tidak sinkron, dan juga melewati nama kelas. Setiap kali dengan cara yang berbeda. Satu-satunya hal yang dapat Anda pegang adalah urutan nama di dalam css - konstan (jika tidak semuanya akan rusak, dalam css urutannya penting). Nomor posisi kelas dalam file dikodekan dalam awalan satu huruf. Anda dapat mengambil pengodean dalam 52 ([a-zA-Z] +) atau 64 ([a-zA-Z0-9 _-] +) karakter. Hal utama di sini adalah jangan lupa untuk meletakkan awalan pelindung dalam kasus dengan angka atau tanda hubung.

/* Bird */
.a { }
.b { }
/* Cat */
.c { }
.d { }

Tampaknya terlihat bagus - nama-nama dikompres sebanyak mungkin. Tetapi yang menarik adalah bahwa paket web tidak sinkron, dan setiap peluncuran, dan terutama ketika server dan klien rakitan simultan diluncurkan secara paralel, menerima file dalam cara yang kacau, seperti halnya nama-nama kelas. Terima kasih untuk kecepatannya, tapi ini mengganggu.

/* Bird */
.c { }
.d { }
/* Cat */
.a { }
.b { }

Anda lihat, menangkap ketidakcocokan pesanan file.

Kami memperbaiki perilaku ini dengan mengingat file, dari mana kelas berasal, dan nomor posisi mereka.

/* Bird */
.a { }
.b { }
/* Cat */
.a { }
.b { }

Menyimpan pesanan di dalam file. Tetapi Anda harus membedakan file satu sama lain. Hash dari path file akan membantu untuk menghindari kebingungan.

/* Bird */
.a_k3bvEft8 { }
.b_k3bvEft8 { }
/* Cat */
.a_oRzvA1Gb { }
.b_oRzvA1Gb { }

('_' tidak diperlukan di sini, itu hanya untuk tujuan ilustrasi. Hash memiliki panjang yang stabil, tidak seperti awalan, dan tidak ada tabrakan)

Kami telah memperoleh nama kelas yang benar-benar unik untuk proyek, tetapi berisi urutan berulang.

Dalam proyek kami, dari file css 50 Kb dan js 47 Kb, kami mendapat css 30 Kb dan js 28 Kb [total 58 Kb, brotli].
Hemat hampir 40Kb. Ukuran css kritis dan ukuran html akan sedikit berkurang.

Masih menulis kelas untuk memproses data dari webpack dan melakukan panggilan dalam konfigurasi css-loader (getLocalIdent)

PS Anda dapat melangkah lebih jauh dan menyimpan path file, mengurutkan path, dan juga menggantinya dengan strategi satu huruf, tetapi ini lebih buruk dalam hal caching jangka panjang, ditambah Anda perlu membuat beberapa lintasan dalam perakitan dan merakit klien / server secara berurutan.

PS2 Anda dapat mencoba proyek Anda sekarang, jika Anda mengambil kode di sini

PS3. Dalam produksi, kami mengompres file * .css dan * style.js sebesar 93%. Kami mentransfer 71,6Kb dari 1,1Mb file yang belum dibongkar (brotli)

All Articles