"Jackal": peras bagian depan

Hai Saya Vanya, pemimpin tim platform di Tinkoff Business.

Hiburan favorit saya adalah membuka tab DevTools dan memeriksa berapa berat artefak situs web. Dalam artikel ini saya akan memberi tahu Anda bagaimana kami mengurangi berat aplikasi hingga 30% dengan bantuan tim front-end platform dalam satu hari tanpa mengubah kode situs. Tidak ada trik dan registrasi - hanya nginx, docker dan node.js (opsional).




Mengapa


Sekarang aplikasi front-end sangat berat. Artefak yang dikoleksi dapat memiliki berat 2-3 MB, atau bahkan lebih. Namun, algoritma kompresi membantu pengguna.

Sampai baru-baru ini, kami hanya menggunakan Gzip, yang diperkenalkan ke dunia pada tahun 1992. Ini mungkin adalah algoritma kompresi paling populer di web, didukung oleh semua browser di atas IE 6.

Biarkan saya mengingatkan Anda bahwa tingkat kompresi Gzip bervariasi dalam kisaran dari 1 hingga 9 (lebih banyak lebih efisien), dan Anda dapat mengompresnya dengan cepat atau statis.

  • "On the fly" (dinamis) - artefak disimpan dalam bentuk yang diterima setelah perakitan, kompresi mereka terjadi selama pengiriman ke klien. Dalam kasus kami, pada level nginx.
  • Statis - artefak dikompresi setelah perakitan, dan server HTTP mengirimkannya ke klien "sebagaimana adanya".

Jelas, opsi pertama membutuhkan lebih banyak sumber daya server untuk setiap permintaan. Yang kedua adalah pada tahap perakitan dan persiapan aplikasi.

Frontend kami dikompresi secara dinamis oleh tingkat keempat. Saya akan menunjukkan perbedaan antara artefak terkompresi dan asli:
Tingkat kompresi
Berat Artefak, Kb
Waktu kompresi, ms
0
2522
-
1
732
42
2
702
44
3
683
48
4
636
55
5
612
65
6
604
77
7
604
80
8
603
104
9
601
102

Anda mungkin memperhatikan bahwa bahkan tingkat keempat mengurangi ukuran artefak sebanyak 4 kali! Dan perbedaan antara level keempat dan kesembilan adalah 35 Kb, yaitu 1,3% dari aslinya, tetapi waktu kompresi 2 kali lebih lama.

Dan baru-baru ini, kami berpikir: mengapa tidak beralih ke Brotli? Ya, dan pada tingkat kompresi paling kuat!

Omong-omong, algoritma ini diperkenalkan oleh Google pada tahun 2015 dan memiliki 11 level kompresi. Pada saat yang sama, tingkat keempat Brotli lebih efektif daripada yang kesembilan di Gzip. Saya termotivasi dan dengan cepat melemparkan kode untuk mengompres artefak dengan algoritma Brotli. Hasilnya disajikan di bawah ini:
Tingkat kompresi
Berat Artefak, Kb
Waktu kompresi, ms
0
2522
-
1
662
128
2
612
155
3
601
156
4
574
202
5
526
227
6
512
249
7
501
303
8
496
359
9
492
420
10
452
3708
11
446
8257

Namun, tabel menunjukkan bahwa bahkan tingkat kompresi Brotli pertama memakan waktu lebih lama daripada tingkat kesembilan di Gzip. Dan level terakhir - sebanyak 8,3 detik! Itu mengingatkan saya.

Di sisi lain, hasilnya jelas mengesankan. Selanjutnya, saya mencoba mentransfer kompresi ke nginx - google the dokumentasi . Semuanya ternyata sangat sederhana:

brotli on; brotli_comp_level 11; brotli_types text/plain text/css application/javascript; 

Dia mengumpulkan gambar buruh pelabuhan, meluncurkan wadah dan sangat terkejut:



Waktu pengunduhan file saya meningkat sepuluh kali lipat - dari 100 ms menjadi 5 detik! Aplikasi menjadi tidak mungkin digunakan.

Setelah mempelajari dokumentasi lebih dalam, saya menyadari bahwa Anda dapat mendistribusikan secara statis. Saya menggunakan skrip yang ditulis sebelumnya, mengompresi artefak yang sama, memasukkannya ke dalam wadah, dan meluncurkannya. Unduh kali kembali normal - kemenangan! Namun, masih terlalu dini untuk bersukacita, karena proporsi browser yang mendukung jenis kompresi ini adalah sekitar 80% .

Ini berarti Anda harus menjaga kompatibilitas ke belakang, sementara di samping itu Anda ingin menggunakan level Gzip yang paling efektif. Maka muncul ide untuk membuat utilitas kompresi file, yang kemudian mendapat nama "Jackal".



Apa yang kita butuhkan


Nginx, Docker dan Node.js, meskipun Anda juga bisa menggunakan bash jika mau.
Dengan Nginx, hampir semuanya jelas:

 brotli off; brotli_static on; gzip_static on; 

Tapi apa yang harus dilakukan dengan aplikasi yang belum berhasil memperbarui gambar buruh pelabuhan? Benar, tambahkan kompatibilitas ke belakang:

 gzip on; gzip_level 4; gzip_types text/plain text/css application/javascript; 

Saya akan menjelaskan prinsip operasi:


Pada setiap permintaan, klien mengirim header Terima-Pengkodean, yang mencantumkan algoritma kompresi yang didukung, dipisahkan oleh koma. Biasanya itu mengempis, gzip, br.

Jika klien memiliki br di baris, maka nginx mencari file dengan ekstensi .br, jika tidak ada file seperti itu dan klien mendukung Gzip, maka ia mencari .gz. Jika tidak ada file seperti itu, maka itu akan mengguncang "on the fly" dan mengembalikannya dengan tingkat kompresi keempat.

Jika klien tidak mendukung segala jenis kompresi, maka server akan mengeluarkan artefak dalam bentuk aslinya.

Namun, muncul masalah: gambar nginx docker kami tidak mendukung modul Brotli. Sebagai dasar, saya mengambil gambar buruh pelabuhan yang sudah jadi .

Dockerfile untuk "mengepak" nginx dalam suatu proyek
 FROM fholzer/nginx-brotli #      RUN rm -rf /usr/share/nginx/html/ #      COPY app/nginx /etc/nginx/conf.d/ #      COPY dist/ /usr/share/nginx/html/ #  CMD nginx -c /etc/nginx/conf.d/nginx.conf 


Kami menemukan penyeimbangan lalu lintas, tetapi dari mana mendapatkan artefak? Di sinilah Jackal datang untuk menyelamatkan.

Jackal


Ini adalah utilitas untuk mengompresi statika aplikasi Anda.

Sekarang ini adalah tiga skrip node.js yang dibungkus dengan gambar buruh pelabuhan dengan simpul: alpine. Mari kita bahas skripnya.

base-compressor - sebuah skrip yang mengimplementasikan logika kompresi dasar.

Masukan argumen:

  1. Fungsi kompresi - fungsi javascript apa pun, Anda dapat menerapkan algoritma kompresi Anda sendiri.
  2. Parameter kompresi - objek dengan parameter yang diperlukan untuk fungsi yang ditransfer.
  3. Ekstensi - perluasan artefak kompresi. Harus ditentukan dimulai dengan karakter titik.

gzip.js - file dengan panggilan kompresor-dasar dengan fungsi Gzip yang dilewatkan dari paket zlib dan menunjukkan tingkat kompresi kesembilan.

brotli.js - mengajukan dengan panggilan kompresor-dasar dengan fungsi Brotli yang dilewatkan dari paket npm yang sama dan menunjukkan tingkat kompresi ke-11.

Dockerfile menciptakan gambar Jackal
 FROM node:8.12.0-alpine #     COPY scripts scripts #  package.json  package-lock.json   COPY package*.json scripts/ #      WORKDIR scripts #    #    node_modules/   #  ,     RUN npm ci #     CMD node gzip.js | node brotli.js 


Kami menemukan cara kerjanya, sekarang Anda dapat berjalan dengan aman:

 docker run \ -v $(pwd)/dist:/scripts/dist \ -e 'dirs=["dist/"]' \ -i mngame/shakal 

  • -v $ (pwd) / dist: / scripts / dist - tentukan direktori lokal mana yang akan dipertimbangkan dalam direktori (tautan ke mount). Menentukan direktori skrip diperlukan, karena berfungsi di dalam wadah.
  • -e 'dirs = ["dist /"]' - tentukan dir parameter lingkungan - array baris yang menggambarkan direktori di dalam skrip / yang akan dikompresi.
  • -i mngame / shakal - menetapkan gambar dengan docker.io.

Dalam direktori yang ditentukan, skrip secara kompres mengompresi semua file dengan ekstensi yang ditentukan .js, .json, .html, .css dan menyimpan file dengan ekstensi .br dan .gz di sebelahnya. Pada proyek kami, proses ini memakan waktu sekitar dua menit dengan berat semua artefak sekitar 6 MB.

Pada titik ini, dan mungkin bahkan lebih awal, Anda mungkin berpikir: "buruh pelabuhan apa? Simpul yang mana? Mengapa tidak menambahkan dua paket saja ke diri Anda di package.json dari proyek dan menelepon langsung di postbuild? "

Secara pribadi, itu menyakitkan saya untuk melihat kapan, demi menjalankan linter di CI, proyek menginstal 100 paket untuk dirinya sendiri, yang membutuhkan maksimum 10 pada tahap linting.Ini adalah waktu agen, waktu Anda, setelah semua, waktu untuk memasarkan.

Dalam kasus buruh pelabuhan, kami mendapatkan gambar pra-rakitan di mana segala sesuatu yang diperlukan untuk kompresi diinstal. Jika Anda tidak perlu memampatkan apa pun sekarang - jangan memampatkan. Butuh serat - jalankan saja, perlu tes - jalankan saja. Plus, kami mendapatkan versi Jackal yang baik: kami tidak perlu memperbarui dependensinya di setiap proyek - cukup lepaskan versi baru, dan gunakan tag terbaru untuk proyek tersebut.

Hasil:


  • Ukuran artefak telah berubah dari 636 Kb menjadi 446 Kb.
  • Ukuran persentase menurun 30%.
  • Waktu pengunduhan berkurang 10-12%.
  • Waktu dekompresi, berdasarkan artikel , tetap sama.

Total


Anda dapat membantu pengguna Anda sekarang, tepat dengan PR berikutnya: tambahkan langkah setelah perakitan - kompresi "Jackal", dan kemudian kirimkan artefak ke wadah Anda. Setelah setengah jam, pengguna Anda merasa sedikit lebih baik.

Kami berhasil mengurangi bobot front-end hingga 30% - Anda akan berhasil! Semua situs mudah.

Referensi:


Source: https://habr.com/ru/post/id474632/


All Articles