Codelab ini mempelajari cara meminifikasi dan mengompresi paket JavaScript untuk aplikasi berikut dapat meningkatkan performa halaman dengan mengurangi ukuran permintaan aplikasi.
Ukur
Sebelum mulai menambahkan pengoptimalan, sebaiknya Anda menganalisis status aplikasi saat ini terlebih dahulu.
- Untuk melihat pratinjau situs, tekan View App, lalu tekan Fullscreen .
Aplikasi ini, yang juga dibahas di codelab "Menghapus kode yang tidak digunakan", memungkinkan Anda memilih anak kucing favorit Anda. 🐈
Sekarang lihat seberapa besar aplikasi ini:
- Tekan `Control+Shift+J` (atau `Command+Option+J` di Mac) untuk membuka DevTools.
- Klik tab Network
- Centang kotak Disable cache.
- Muat ulang aplikasi.
Meskipun banyak progres yang dibuat dalam codelab "Remove unused code" untuk memangkas ukuran paket ini, 225 KB masih cukup besar.
Minifikasi
Pertimbangkan blok kode berikut.
function soNice() {
let counter = 0;
while (counter < 100) {
console.log('nice');
counter++;
}
}
Jika fungsi ini disimpan dalam filenya sendiri, ukuran filenya sekitar 112 B (byte).
Jika semua spasi kosong dihapus, kode yang dihasilkan akan terlihat seperti ini:
function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}
Ukuran file sekarang akan menjadi sekitar 83 B. Jika dirusak lebih lanjut dengan mengurangi panjang nama variabel dan mengubah beberapa ekspresi, kode akhir mungkin akan terlihat seperti ini:
function soNice(){for(let i=0;i<100;)console.log("nice"),i++}
Ukuran file kini mencapai 62 B.
Dengan setiap langkah, kode menjadi lebih sulit dibaca. Namun, mesin JavaScript browser menafsirkan setiap variabel ini dengan cara yang sama persis. Manfaat obfuscate kode dengan cara ini dapat membantu mencapai ukuran file yang lebih kecil. Awalnya, 112 B tidak banyak, tapi masih ada pengurangan ukuran 50%!
Dalam aplikasi ini, webpack versi 4 digunakan sebagai pemaket modul. Versi spesifik dapat dilihat di package.json
.
"devDependencies": {
//...
"webpack": "^4.16.4",
//...
}
Versi 4 sudah meminifikasi paket secara default selama mode produksi. Library ini menggunakan plugin TerserWebpackPlugin
untuk Terser.
Terser adalah alat populer yang digunakan untuk mengompresi kode JavaScript.
Untuk mendapatkan gambaran tentang tampilan kode yang diminifikasi, klik
main.bundle.js
sambil tetap berada di panel Jaringan DevTools. Sekarang, klik tab
Response.
Kode dalam bentuk akhirnya, yang diminifikasi dan dimodifikasi, ditampilkan dalam isi respons.
Untuk mengetahui seberapa besar ukuran paket jika tidak diminifikasi, buka
webpack.config.js
dan perbarui konfigurasi mode
.
module.exports = {
mode: 'production',
mode: 'none',
//...
Muat ulang aplikasi dan lihat lagi ukuran paket melalui panel Network DevTools
Perbedaan yang cukup besar! 😅
Pastikan untuk mengembalikan perubahan di sini sebelum melanjutkan.
module.exports = {
mode: 'production',
mode: 'none',
//...
Penyertaan proses untuk meminifikasi kode dalam aplikasi bergantung pada alat yang Anda gunakan:
- Jika webpack v4 atau yang lebih baru digunakan, Anda tidak perlu melakukan pekerjaan tambahan karena kode diminifikasi secara default dalam mode produksi. 👍
- Jika webpack versi lama digunakan, instal dan sertakan
TerserWebpackPlugin
ke dalam proses build webpack. Dokumentasi ini menjelaskan hal ini secara mendetail. - Plugin minifikasi lainnya juga ada dan dapat digunakan, seperti BabelMinifyWebpackPlugin dan ClosureCompilerPlugin.
- Jika pemaket modul tidak digunakan sama sekali, gunakan Terser sebagai alat CLI atau sertakan langsung sebagai dependensi.
Kompresi
Meskipun istilah "kompresi" terkadang digunakan secara longgar untuk menjelaskan bagaimana kode dikurangi selama proses minifikasi, istilah tersebut sebenarnya tidak dikompresi dalam arti.
Kompresi biasanya mengacu pada kode yang telah dimodifikasi menggunakan algoritma kompresi data. Tidak seperti minifikasi yang pada akhirnya memberikan kode yang benar-benar valid, kode yang dikompresi perlu didekompresi sebelum digunakan.
Dengan setiap permintaan dan respons HTTP, browser dan server web dapat menambahkan
headers untuk menyertakan
informasi tambahan tentang aset yang diambil atau diterima. Hal ini dapat
dilihat di tab Headers
dalam panel Jaringan DevTools tempat tiga jenis
ditampilkan:
- General mewakili header umum yang relevan dengan seluruh interaksi respons permintaan.
- Header Respons menampilkan daftar header khusus untuk respons sebenarnya dari server.
- Header Permintaan menampilkan daftar header yang dilampirkan ke permintaan oleh klien.
Lihat header accept-encoding
di Request Headers
.
accept-encoding
digunakan oleh browser untuk menentukan format encoding
konten, atau algoritma kompresi yang didukungnya. Ada banyak
algoritma kompresi teks di luar sana, tetapi hanya ada tiga yang
didukung di sini untuk kompresi (dan dekompresi) permintaan jaringan HTTP:
- Gzip (
gzip
): Format kompresi yang paling banyak digunakan untuk interaksi server dan klien. Deflate dibuat berdasarkan algoritma Deflate dan didukung di semua browser saat ini. - Deflat (
deflate
): Tidak biasa digunakan. - Brotli (
br
): Algoritma kompresi baru yang bertujuan untuk lebih meningkatkan rasio kompresi, yang dapat menghasilkan pemuatan halaman yang lebih cepat. Alat ini didukung di sebagian besar browser versi terbaru.
Aplikasi contoh dalam tutorial ini identik dengan aplikasi yang diselesaikan dalam codelab "Menghapus kode yang tidak digunakan", kecuali bahwa Express kini digunakan sebagai framework server. Dalam beberapa bagian berikutnya, kompresi statis dan dinamis akan dibahas.
Kompresi dinamis
Kompresi dinamis melibatkan kompresi aset dengan cepat saat diminta oleh browser.
Kelebihan
- Anda tidak perlu membuat dan mengupdate versi terkompresi yang tersimpan dari aset.
- Mengompresi dengan cepat berfungsi sangat baik untuk halaman web yang dihasilkan secara dinamis.
Kekurangan
- Mengompresi file pada tingkat yang lebih tinggi untuk mencapai rasio kompresi yang lebih baik memerlukan waktu lebih lama. Hal ini dapat menyebabkan hit performa saat pengguna menunggu aset untuk dikompresi sebelum dikirim oleh server.
Kompresi dinamis dengan Node/Express
File server.js
bertanggung jawab untuk menyiapkan server Node yang menghosting
aplikasi.
const express = require('express');
const app = express();
app.use(express.static('public'));
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
Yang dilakukan saat ini adalah mengimpor express
dan menggunakan middleware express.static
untuk memuat semua file HTML, JS, dan CSS statis di
direktori public/
(dan file tersebut dibuat oleh webpack dengan setiap build).
Untuk memastikan semua aset dikompresi setiap kali diminta, library middleware kompresi dapat
digunakan. Mulailah dengan menambahkannya sebagai devDependency
di package.json
:
"devDependencies": {
//...
"compression": "^1.7.3"
},
Lalu impor ke file server, server.js
:
const express = require('express');
const compression = require('compression');
Dan tambahkan sebagai middleware sebelum express.static
dipasang:
//...
const app = express();
app.use(compression());
app.use(express.static('public'));
//...
Sekarang, muat ulang aplikasi dan lihat ukuran paket di panel Network.
Dari 225 KB menjadi 61,6 KB! Dalam Response Headers
sekarang, header content-encoding
menunjukkan bahwa server mengirimkan file ini yang dienkode dengan gzip
.
Kompresi statis
Ide di balik kompresi statis adalah untuk membuat aset dikompresi dan dihemat terlebih dahulu.
Kelebihan
- Latensi karena tingkat kompresi yang tinggi bukan lagi masalah penting. Tidak perlu melakukan apa pun dengan cepat untuk mengompresi file karena sekarang file tersebut dapat diambil langsung.
Kekurangan
- Aset harus dikompresi dengan setiap build. Waktu build dapat meningkat secara signifikan jika tingkat kompresi tinggi digunakan.
Kompresi statis dengan Node/Express dan webpack
Karena kompresi statis melibatkan kompresi file terlebih dahulu, setelan webpack
dapat diubah untuk mengompresi aset sebagai bagian dari langkah build.
CompressionPlugin
dapat digunakan untuk ini.
Mulailah dengan menambahkannya sebagai devDependency
di package.json
:
"devDependencies": {
//...
"compression-webpack-plugin": "^1.1.11"
},
Seperti plugin webpack lainnya, impor plugin webpack dalam file konfigurasi,
webpack.config.js:
const path = require("path");
//...
const CompressionPlugin = require("compression-webpack-plugin");
Dan sertakan dalam array plugins
:
module.exports = {
//...
plugins: [
//...
new CompressionPlugin()
]
}
Secara default, plugin mengompresi file build menggunakan gzip
. Lihat dokumentasi untuk mempelajari cara menambahkan opsi untuk menggunakan algoritma lain atau menyertakan/mengecualikan file tertentu.
Saat aplikasi dimuat ulang dan di-build ulang, versi terkompresi paket utama
kini akan dibuat. Buka Glitch Console untuk melihat isi direktori public/
final yang disalurkan oleh server Node.
- Klik tombol Alat.
- Klik tombol Konsol.
- Di konsol, jalankan perintah berikut untuk beralih ke direktori
public
dan melihat semua filenya:
cd public
ls
Versi paket yang di-zip, main.bundle.js.gz
, kini juga disimpan di sini. CompressionPlugin
juga mengompresi index.html
secara default.
Langkah berikutnya yang perlu dilakukan adalah memberi tahu server untuk mengirim file yang di-zip sebagai file gzip ini setiap kali versi JS aslinya diminta. Hal ini dapat dilakukan
dengan menentukan rute baru di server.js
sebelum file ditayangkan dengan
express.static
.
const express = require('express'); const app = express(); app.get('*.js', (req, res, next) => { req.url = req.url + '.gz'; res.set('Content-Encoding', 'gzip'); next(); }); app.use(express.static('public')); //...
app.get
digunakan untuk memberi tahu server cara merespons permintaan GET untuk endpoint tertentu. Fungsi callback kemudian digunakan untuk menentukan cara menangani permintaan ini. Rutenya berfungsi seperti ini:
- Menentukan
'*.js'
sebagai argumen pertama berarti argumen ini berfungsi untuk setiap endpoint yang diaktifkan untuk mengambil file JS. - Dalam callback,
.gz
dilampirkan ke URL permintaan dan header responsContent-Encoding
ditetapkan kegzip
. - Terakhir,
next()
akan memastikan urutan berlanjut ke callback yang mungkin berikutnya.
Setelah aplikasi dimuat ulang, lihat panel Network
sekali lagi.
Sama seperti sebelumnya, pengurangan ukuran paket yang signifikan.
Kesimpulan
Codelab ini membahas proses meminifikasi dan mengompresi kode sumber. Kedua teknik ini akan menjadi default di banyak alat yang tersedia saat ini. Oleh karena itu, penting untuk mengetahui apakah toolchain Anda sudah mendukungnya atau apakah Anda harus mulai menerapkan kedua proses tersebut sendiri.