Kullanılmayan kodu kaldırın

Bu codelab'de, kullanılmayan ve gereksiz bağımlılıkları kaldırarak aşağıdaki uygulamanın performansını iyileştirin.

Uygulama ekran görüntüsü

Ölçüm

Optimizasyon eklemeden önce bir web sitesinin ne kadar iyi performans gösterdiğini ölçmek her zaman iyi bir fikirdir.

  • Siteyi önizlemek için Uygulamayı Görüntüle'ye, ardından Tam Ekran'a tam ekran basın.

En sevdiğiniz yavru kediyi tıklayın. Bu uygulamada Firebase'in Realtime Database'i kullanıldığı için puan gerçek zamanlı olarak güncellenir ve uygulamayı kullanan diğer tüm kullanıcılarla senkronize edilir. 🐈

  1. Geliştirici Araçları'nı açmak için "Kontrol+Üst Karakter+J" (veya Mac'te "Komut+Option+J") tuşlarına basın.
  2. sekmesini tıklayın.
  3. Önbelleği devre dışı bırak onay kutusunu işaretleyin.
  4. Uygulamayı yeniden yükleyin.

Orijinal paket boyutu 992 KB

Bu basit uygulamayı yüklemek için neredeyse 1 MB'lık JavaScript gönderiliyor.

Geliştirici Araçları'ndaki proje uyarılarına göz atın.

  • Konsol sekmesini tıklayın.
  • Filter girişinin yanındaki seviyeler açılır menüsünde Warnings'ün etkinleştirildiğinden emin olun.

Uyarı filtresi

  • Gösterilen uyarıya göz atın.

Konsol uyarısı

Bu uygulamada kullanılan kitaplıklardan biri olan Firebase, geliştiricilere paketin tamamını değil, yalnızca kullanılan bileşenleri içe aktarmamaları gerektiğini bildiren bir uyarı sağlayarak iyi bir samaritan örneği gösteriyor. Diğer bir deyişle, bu uygulamanın daha hızlı yüklenmesini sağlamak için kaldırılabilecek kullanılmayan kitaplıklar vardır.

Belirli bir kitaplığın kullanıldığı ancak daha basit bir alternatifin olabileceği durumlar da vardır. Gereksiz kitaplıkları kaldırma kavramı bu eğitimde daha ayrıntılı olarak ele alınmaktadır.

Paketi analiz etme

Uygulamada iki temel bağımlılık vardır:

  • Firebase: iOS, Android veya web uygulamaları için çeşitli faydalı hizmetler sunan bir platformdur. Burada, her bir yavru kedinin bilgilerini gerçek zamanlı olarak depolamak ve senkronize etmek için Realtime Database kullanılır.
  • Moment.js: JavaScript'te tarihleri işlemeyi kolaylaştıran bir yardımcı kitaplıktır. Her yavrunun doğum tarihi Firebase veritabanında saklanır ve yavrunun hafta cinsinden yaşını hesaplamak için moment kullanılır.

Yalnızca iki bağımlılık, paket boyutunun neredeyse 1 MB olmasına nasıl katkıda bulunabilir? Bunun nedenlerinden biri, her bağımlılığın kendi bağımlılıkları olabileceğidir. Bu nedenle, bağımlılık "ağacının" her derinliği/dalını dikkate alırsak ikiden çok bağımlı vardır. Çok sayıda bağımlılık eklenirse bir uygulamanın nispeten hızlı bir şekilde büyük hale gelmesi kolaydır.

Neler olduğunu daha iyi anlamak için paketleyiciyi analiz edin. Bunu yapmanıza yardımcı olabilecek, topluluk tarafından oluşturulmuş çeşitli araçlar vardır (ör. webpack-bundle-analyzer).

Bu aracın paketi, uygulamaya devDependency olarak zaten eklenmiştir.

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

Yani doğrudan webpack yapılandırma dosyasında kullanılabilir. Dosyayı webpack.config.js'ün en başına aktarın:

const path = require("path");

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

Şimdi bu işlevi, dosyanın en sonuna plugins dizisine eklenecek bir eklenti olarak ekleyin:

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

Uygulama yeniden yüklendiğinde, uygulamanın kendisi yerine paketin tamamının görselleştirmesini görürsünüz.

Webpack Bundle Analyzer

Yavru kedileri görmek kadar sevimli olmasa da yine de son derece faydalıdır. Fareyle paketlerin üzerine geldiğinizde boyutları üç farklı şekilde gösterilir:

İstatistik boyutu Herhangi bir küçültme veya sıkıştırma işleminden önceki boyut.
Ayrıştırılmış boyut Derlendikten sonra paket içindeki gerçek paketin boyutu. Webpack'in 4. sürümü (bu uygulamada kullanılır) derlenmiş dosyaları otomatik olarak küçültür. Bu nedenle, bu dosya istatistik boyutundan daha küçüktür.
Sıkıştırılmış boyut gzip kodlamasıyla sıkıştırıldıktan sonra paketin boyutu. Bu konu ayrı bir kılavuzda ele alınmıştır.

webpack-bundle-analyzer aracıyla, paketin büyük bir yüzdesini oluşturan kullanılmayan veya gereksiz paketleri tespit etmek daha kolaydır.

Kullanılmayan paketleri kaldırma

Görselleştirme, firebase paketinin yalnızca bir veritabanından çok daha fazlasını içerdiğini gösterir. Buna aşağıdakiler gibi ek paketler dahildir:

  • firestore
  • auth
  • storage
  • messaging
  • functions

Bunların tümü Firebase tarafından sağlanan muhteşem hizmetlerdir (daha fazla bilgi edinmek için dokümanlara göz atın). Ancak bunların hiçbiri uygulamada kullanılmadığından tümünün içe aktarılmasına gerek yoktur.

Uygulamayı tekrar görmek için webpack.config.js'teki değişiklikleri geri alın:

  • Eklenti listesinden BundleAnalyzerPlugin'ü kaldırın:
plugins: [
  //...
  new BundleAnalyzerPlugin()
];
  • Ardından, kullanılmayan içe aktarma işlemini dosyanın üst kısmından kaldırın:
const path = require("path");

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

Uygulama artık normal şekilde yüklenecektir. Firebase içe aktarma işlemlerini güncellemek için src/index.js değerini değiştirin.

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

Artık uygulama yeniden yüklendiğinde DevTools uyarısı gösterilmiyor. DevTools panelini açtığınızda paket boyutunda önemli bir azalma da görebilirsiniz:

Paket boyutu 480 KB'a düşürüldü

Paket boyutunun yarısından fazlası kaldırıldı. Firebase birçok farklı hizmet sunar ve geliştiricilere yalnızca gerçekten ihtiyaç duyulanları dahil etme seçeneği sunar. Bu uygulamada, tüm verileri depolamak ve senkronize etmek için yalnızca firebase/database kullanıldı. Farklı hizmetlerin her biri için API yüzeyini ayarlayan firebase/app içe aktarma işlemi her zaman gereklidir.

lodash gibi diğer popüler kitaplıklar da geliştiricilerin paketlerinin farklı bölümlerini seçerek içe aktarmasına olanak tanır. Çok fazla çalışma yapmadan, bir uygulamadaki kitaplık içe aktarma işlemlerini yalnızca kullanılanları içerecek şekilde güncellemek önemli performans iyileştirmelerine neden olabilir.

Paket boyutu oldukça küçültülmüş olsa da yapılması gereken daha çok iş var. 😈

Gereksiz paketleri kaldırma

Firebase'den farklı olarak, moment kitaplığının bölümlerini içe aktarmak o kadar kolay değildir ancak tamamen kaldırılabilir mi?

Her sevimli yavru kedinin doğum günü, Firebase veritabanında Unix biçiminde (milisaniye) depolanır.

Unix biçiminde depolanan doğum tarihleri

Bu, 1 Ocak 1970 00:00 UTC tarihinden itibaren geçen milisaniye sayısıyla temsil edilen belirli bir tarih ve saatin zaman damgası. Mevcut tarih ve saat aynı biçimde hesaplanabiliyorsa her yavrunun yaşını hafta cinsinden bulmak için küçük bir işlev oluşturulabilir.

Her zaman olduğu gibi, bu adımları uygularken kopyalayıp yapıştırmamaya çalışın. src/index.js içindeki içe aktarma işlemlerinden moment'ü kaldırarak başlayın.

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

Veritabanı değerlerimizdeki değişiklikleri işleyen bir Firebase etkinlik dinleyicisi vardır:

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

Bunun üzerine, belirli bir tarihten itibaren hafta sayısını hesaplamak için küçük bir işlev ekleyin:

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);
}

Bu işlevde, geçerli tarih ve saat (new Date).getTime() ile doğum tarihi (birthDate bağımsız değişkeni, milisaniye cinsinden) arasındaki milisaniye farkı hesaplanır ve tek bir haftadaki milisaniye sayısına bölünür.

Son olarak, bu işlevden yararlanarak etkinlik dinleyicisinde moment öğesinin tüm örnekleri kaldırılabilir:

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>
    `})
});

Şimdi uygulamayı yeniden yükleyin ve paneline bir kez daha göz atın.

Paket boyutu 225 KB&#39;a düşürüldü

Paketimizin boyutu bir kez daha yarıdan fazla küçültüldü.

Sonuç

Bu kod laboratuvarını tamamladığınızda, belirli bir paketin nasıl analiz edileceğini ve kullanılmayan veya gereksiz paketlerin kaldırılmasının neden çok yararlı olabileceğini iyice anlamış olacaksınız. Bir uygulamayı bu teknikle optimize etmeye başlamadan önce bunun daha büyük uygulamalarda önemli ölçüde daha karmaşık olabileceğini bilmek önemlidir.

Kullanılmayan kitaplıkları kaldırma ile ilgili olarak, paketin hangi bölümlerinin kullanıldığını ve hangi bölümlerinin kullanılmadığını öğrenmeye çalışın. Hiçbir yerde kullanılmadığı anlaşılan gizemli görünümlü bir paket için bir adım geri çekilin ve hangi üst düzey bağımlılıkların buna ihtiyaç duyabileceğini kontrol edin. Bunları birbirinden ayırmanın bir yolunu bulmaya çalışın.

Gereksiz kitaplıkları kaldırma söz konusu olduğunda işler biraz daha karmaşık olabilir. Ekibinizle yakın bir şekilde çalışmak ve kod tabanının bazı kısımlarını basitleştirme potansiyeli olup olmadığını görmek önemlidir. Bu uygulamada moment değerini kaldırmak her zaman doğru bir işlem gibi görünebilir ancak ele alınması gereken saat dilimleri ve farklı yerel ayarlar varsa ne olur? Ya da daha karmaşık tarih işlemleri varsa? Tarihleri/saatleri değiştirirken ve ayrıştırırken işler çok karmaşık hale gelebilir. moment ve date-fns gibi kitaplıklar bu işlemi önemli ölçüde basitleştirir.

Her şeyin bir bedeli vardır. Üçüncü taraf kitaplıklarına güvenmek yerine özel bir çözüm sunmanın karmaşıklığına ve çabasına değip değmeyeceğini değerlendirmek önemlidir.