Menghapus kode yang tidak digunakan

Dalam codelab ini, tingkatkan performa aplikasi berikut dengan menghapus dependensi yang tidak digunakan dan tidak diperlukan.

Screenshot aplikasi

Ukur

Sebaiknya ukur terlebih dahulu seberapa baik performa situs sebelum menambahkan pengoptimalan.

  • Untuk melihat pratinjau situs, tekan View App. Kemudian, tekan Fullscreen layar penuh.

Silakan klik anak kucing favorit Anda. Realtime Database Firebase digunakan dalam aplikasi ini, sehingga skor diperbarui secara real-time dan disinkronkan dengan setiap orang lain yang menggunakan aplikasi. 🐈

  1. Tekan `Control+Shift+J` (atau `Command+Option+J` di Mac) untuk membuka DevTools.
  2. Klik tab Jaringan.
  3. Centang kotak Disable cache.
  4. Muat ulang aplikasi.

Ukuran paket asli 992 KB

JavaScript berukuran hampir 1 MB dikirim untuk memuat aplikasi sederhana ini.

Lihat peringatan project di DevTools.

  • Klik tab Console.
  • Pastikan Warnings diaktifkan di dropdown level di samping input Filter.

Filter peringatan

  • Lihat peringatan yang ditampilkan.

Peringatan konsol

Firebase, yang merupakan salah satu library yang digunakan dalam aplikasi ini, memberikan peringatan untuk memberi tahu developer agar tidak mengimpor seluruh paketnya, tetapi hanya komponen yang digunakan. Dengan kata lain, ada library yang tidak digunakan yang dapat dihapus dalam aplikasi ini agar dimuat lebih cepat.

Ada juga kasus saat library tertentu digunakan, tetapi mungkin ada alternatif yang lebih sederhana. Konsep penghapusan library yang tidak diperlukan akan dibahas nanti dalam tutorial ini.

Menganalisis paket

Ada dua dependensi utama dalam aplikasi:

  • Firebase: platform yang menyediakan sejumlah layanan berguna untuk aplikasi iOS, Android, atau aplikasi web. Di sini, Realtime Database digunakan untuk menyimpan dan menyinkronkan informasi untuk setiap anak kucing secara real time.
  • Moment.js: library utilitas yang memudahkan penanganan tanggal di JavaScript. Tanggal lahir setiap anak kucing disimpan di database Firebase, dan moment digunakan untuk menghitung usianya dalam minggu.

Bagaimana hanya dua dependensi dapat berkontribusi pada ukuran paket yang hampir 1 MB? Salah satu alasannya adalah setiap dependensi dapat memiliki dependensinya sendiri, sehingga ada lebih dari dua dependensi jika setiap kedalaman/cabang "hierarki" dependensi dipertimbangkan. Aplikasi dapat dengan mudah menjadi besar dalam waktu yang relatif cepat jika banyak dependensi yang disertakan.

Analisis bundler untuk mendapatkan gambaran yang lebih baik tentang apa yang terjadi. Ada sejumlah alat berbeda yang dibuat komunitas yang dapat membantu melakukannya, seperti webpack-bundle-analyzer.

Paket untuk alat ini sudah disertakan dalam aplikasi sebagai devDependency.

"devDependencies": {
  //...
  "webpack-bundle-analyzer": "^2.13.1"
},

Artinya, plugin ini dapat digunakan langsung di file konfigurasi webpack. Impor di awal webpack.config.js:

const path = require("path");

//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

Sekarang, tambahkan sebagai plugin di bagian paling akhir file dalam array plugins:

module.exports = {
  //...
  plugins: [
    //...
    new BundleAnalyzerPlugin()
  ]
};

Saat aplikasi dimuat ulang, Anda akan melihat visualisasi seluruh paket, bukan aplikasi itu sendiri.

Webpack Bundle Analyzer

Tidak seimut melihat anak kucing 🐱, tetapi sangat membantu. Mengarahkan kursor ke salah satu paket akan menampilkan ukurannya yang direpresentasikan dalam tiga cara berbeda:

Ukuran statistik Ukuran sebelum minifikasi atau kompresi.
Ukuran yang diuraikan Ukuran paket sebenarnya dalam paket setelah dikompilasi. Webpack versi 4 (yang digunakan dalam aplikasi ini) meminimalkan file yang dikompilasi secara otomatis, sehingga ukurannya lebih kecil daripada ukuran stat.
Ukuran Gzip Ukuran paket setelah dikompresi dengan encoding gzip. Topik ini dibahas dalam panduan terpisah.

Dengan alat webpack-bundle-analyzer, Anda dapat lebih mudah mengidentifikasi paket yang tidak digunakan atau tidak diperlukan yang merupakan persentase besar dari paket.

Menghapus paket yang tidak digunakan

Visualisasi ini menunjukkan bahwa paket firebase terdiri dari banyak hal, bukan hanya database. Paket ini mencakup paket tambahan seperti:

  • firestore
  • auth
  • storage
  • messaging
  • functions

Semua ini adalah layanan luar biasa yang disediakan oleh Firebase (dan lihat dokumentasi untuk mempelajari lebih lanjut), tetapi tidak ada satu pun yang digunakan dalam aplikasi, jadi tidak ada alasan untuk mengimpor semuanya.

Kembalikan perubahan di webpack.config.js untuk melihat aplikasi lagi:

  • Hapus BundleAnalyzerPlugin dalam daftar plugin:
plugins: [
  //...
  new BundleAnalyzerPlugin()
];
  • Sekarang, hapus impor yang tidak digunakan dari bagian atas file:
const path = require("path");

//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

Aplikasi akan dimuat secara normal sekarang. Ubah src/index.js untuk memperbarui impor Firebase.

import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';

Sekarang, saat aplikasi dimuat ulang, peringatan DevTools tidak akan muncul. Membuka panel Jaringan DevTools juga menunjukkan pengurangan ukuran paket yang bagus:

Ukuran paket dikurangi menjadi 480 KB

Lebih dari separuh ukuran paket telah dihapus. Firebase menyediakan berbagai layanan dan memberi developer opsi untuk hanya menyertakan layanan yang benar-benar diperlukan. Dalam aplikasi ini, hanya firebase/database yang digunakan untuk menyimpan dan menyinkronkan semua data. Impor firebase/app, yang menyiapkan platform API untuk setiap layanan yang berbeda, selalu diperlukan.

Banyak library populer lainnya, seperti lodash, juga memungkinkan developer mengimpor berbagai bagian paketnya secara selektif. Tanpa banyak pekerjaan, mengupdate impor library dalam aplikasi agar hanya menyertakan apa yang digunakan dapat menghasilkan peningkatan performa yang signifikan.

Meskipun ukuran paket telah dikurangi cukup banyak, masih ada hal lain yang perlu dilakukan. 😈

Menghapus paket yang tidak diperlukan

Tidak seperti Firebase, mengimpor bagian library moment tidak dapat dilakukan dengan mudah, tetapi mungkin dapat dihapus sepenuhnya?

Tanggal lahir setiap anak kucing yang lucu disimpan dalam format Unix (milidetik) di database Firebase.

Tanggal lahir yang disimpan dalam format Unix

Ini adalah stempel waktu tanggal dan waktu tertentu yang diwakili oleh jumlah milidetik yang telah berlalu sejak 1 Januari 1970 00.00 UTC. Jika tanggal dan waktu saat ini dapat dihitung dalam format yang sama, fungsi kecil untuk menemukan usia setiap anak kucing dalam minggu mungkin dapat dibuat.

Seperti biasa, cobalah untuk tidak menyalin dan menempel saat Anda mengikuti langkah-langkah di sini. Mulailah dengan menghapus moment dari impor di src/index.js.

import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';

Ada pemroses peristiwa Firebase yang menangani perubahan nilai di database kita:

favoritesRef.on("value", (snapshot) => { ... })

Di atasnya, tambahkan fungsi kecil untuk menghitung jumlah minggu dari tanggal tertentu:

const ageInWeeks = birthDate => {
  const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
  const diff = Math.abs((new Date).getTime() - birthDate);
  return Math.floor(diff / WEEK_IN_MILLISECONDS);
}

Dalam fungsi ini, perbedaan dalam milidetik antara tanggal dan waktu saat ini (new Date).getTime() dan tanggal lahir (argumen birthDate, sudah dalam milidetik) dihitung dan dibagi dengan jumlah milidetik dalam satu minggu.

Terakhir, semua instance moment dapat dihapus di pemroses peristiwa dengan memanfaatkan fungsi ini:

favoritesRef.on("value", (snapshot) => {
  const { kitties, favorites, names, birthDates } = snapshot.val();
  favoritesScores = favorites;

  kittiesList.innerHTML = kitties.map((kittiePic, index) => {
    const birthday = moment(birthDates[index]);

    return `
      <li>
        <img src=${kittiePic} onclick="favKittie(${index})">
        <div class="extra">
          <div class="details">
            <p class="name">${names[index]}</p>
            <p class="age">${moment().diff(birthday, 'weeks')} weeks old</p>
            <p class="age">${ageInWeeks(birthDates[index])} weeks old</p>
          </div>
          <p class="score">${favorites[index]} ❤</p>
        </div>
      </li>
    `})
});

Sekarang muat ulang aplikasi dan lihat panel Network sekali lagi.

Ukuran paket dikurangi menjadi 225 KB

Ukuran paket kami berkurang lebih dari setengahnya lagi.

Kesimpulan

Dengan codelab ini, Anda akan memiliki pemahaman yang baik tentang cara menganalisis paket tertentu dan alasan mengapa menghapus paket yang tidak digunakan atau tidak diperlukan bisa sangat berguna. Sebelum Anda mulai mengoptimalkan aplikasi dengan teknik ini, perlu diketahui bahwa teknik ini bisa jauh lebih kompleks dalam aplikasi yang lebih besar.

Sehubungan dengan menghapus library yang tidak digunakan, coba cari tahu bagian mana dari paket yang digunakan dan bagian mana yang tidak. Untuk paket yang terlihat misterius dan sepertinya tidak digunakan di mana pun, mundur selangkah dan periksa dependensi tingkat atas mana yang mungkin membutuhkannya. Cobalah untuk menemukan cara yang memungkinkan untuk memisahkan keduanya.

Dalam hal menghapus library yang tidak diperlukan, prosesnya bisa sedikit lebih rumit. Penting untuk bekerja sama dengan tim Anda dan melihat apakah ada potensi untuk menyederhanakan bagian codebase. Menghapus moment dalam aplikasi ini mungkin terlihat seperti hal yang tepat untuk dilakukan setiap saat, tetapi bagaimana jika ada zona waktu dan lokalitas berbeda yang perlu ditangani? Atau, bagaimana jika ada manipulasi tanggal yang lebih rumit? Hal-hal dapat menjadi sangat rumit saat memanipulasi dan mengurai tanggal/waktu, dan library seperti moment dan date-fns menyederhanakannya secara signifikan.

Semuanya adalah kompromi, dan penting untuk mengukur apakah kompleksitas dan upaya untuk meluncurkan solusi kustom sepadan, daripada mengandalkan library pihak ketiga.