Hapus 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 performa situs terlebih dahulu sebelum menambahkan pengoptimalan.

  • Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Kemudian tekan Layar Penuh layar penuh.

Silakan klik anak kucing favorit Anda. Realtime Database Firebase digunakan dalam aplikasi ini, itulah sebabnya 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 Nonaktifkan cache.
  4. Muat ulang aplikasi.

Ukuran paket asli 992 KB

JavaScript hampir 1 MB dikirim untuk memuat aplikasi sederhana ini.

Lihat peringatan project di DevTools.

  • Klik tab Konsol.
  • 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, menjadi orang yang baik dengan 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 di aplikasi ini agar memuat lebih cepat.

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

Menganalisis paket

Ada dua dependensi utama dalam aplikasi:

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

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

Analisis paket untuk mendapatkan gambaran yang lebih baik tentang apa yang terjadi. Ada sejumlah alat buatan 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, file 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 selucu melihat beberapa 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) secara otomatis meminifikasi file yang dikompilasi, itulah sebabnya ukurannya lebih kecil daripada ukuran statis.
Ukuran yang di-gzip Ukuran paket setelah dikompresi dengan encoding gzip. Topik ini dibahas dalam panduan terpisah.

Dengan alat webpack-bundle-analyzer, lebih mudah untuk mengidentifikasi paket yang tidak digunakan atau tidak diperlukan yang membentuk persentase besar paket.

Menghapus paket yang tidak digunakan

Visualisasi 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, sehingga 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 sekarang akan dimuat secara normal. 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 ditampilkan. Membuka panel Jaringan DevTools juga menunjukkan pengurangan ukuran paket yang bagus:

Ukuran paket dikurangi menjadi 480 KB

Lebih dari setengah 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 paket secara selektif. Tanpa melakukan banyak pekerjaan, mengupdate impor library dalam aplikasi agar hanya menyertakan yang digunakan dapat menghasilkan peningkatan performa yang signifikan.

Meskipun ukuran paket telah dikurangi cukup banyak, masih ada pekerjaan yang harus dilakukan. 😈

Menghapus paket yang tidak diperlukan

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

Ulang tahun setiap anak kucing lucu disimpan dalam format Unix (milidetik) di database Firebase.

Tanggal lahir 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, jangan salin dan tempel saat Anda mengikuti tutorial di sini. Mulai 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 atas ini, 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 Jaringan sekali lagi.

Ukuran paket dikurangi menjadi 225 KB

Ukuran paket kami kembali dikurangi lebih dari setengahnya.

Kesimpulan

Dengan codelab ini, Anda akan memiliki pemahaman yang baik tentang cara menganalisis paket tertentu dan alasan paket yang tidak digunakan atau tidak diperlukan sangat berguna untuk dihapus. Sebelum Anda mulai mengoptimalkan aplikasi dengan teknik ini, penting untuk mengetahui bahwa hal ini dapat menjadi jauh lebih kompleks dalam aplikasi yang lebih besar.

Sehubungan dengan menghapus library yang tidak digunakan, coba cari tahu bagian paket mana yang digunakan dan mana yang tidak. Untuk paket yang terlihat misterius dan sepertinya tidak digunakan di mana pun, pertimbangkan kembali dan periksa dependensi tingkat teratas yang mungkin memerlukannya. Coba temukan cara untuk membedakan keduanya.

Dalam hal menghapus library yang tidak diperlukan, hal-hal dapat menjadi sedikit lebih rumit. Anda harus bekerja sama dengan tim 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 yang 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 solusi kustom itu sepadan dengan kompleksitas dan upaya untuk meluncurkannya, bukan mengandalkan library pihak ketiga.