کدهای استفاده نشده را حذف کنید

در این کد لبه، با حذف هر گونه وابستگی استفاده نشده و غیر ضروری، عملکرد برنامه زیر را بهبود بخشید.

اسکرین شات برنامه

اندازه گیری کنید

همیشه ایده خوبی است که قبل از افزودن بهینه سازی، ابتدا میزان عملکرد یک وب سایت را اندازه گیری کنید.

  • برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .

پیش بروید و روی بچه گربه مورد علاقه خود کلیک کنید! پایگاه داده Realtime Firebase در این برنامه استفاده می شود، به همین دلیل است که امتیاز به صورت بلادرنگ به روز می شود و با هر شخص دیگری که از برنامه استفاده می کند هماهنگ می شود. 🐈

  1. «Control+Shift+J» (یا «Command+Option+J» در Mac) را فشار دهید تا DevTools باز شود.
  2. روی تب Network کلیک کنید.
  3. چک باکس Disable cache را انتخاب کنید.
  4. برنامه را دوباره بارگیری کنید.

حجم اصلی باندل 992 کیلوبایت

تقریباً 1 مگابایت جاوا اسکریپت برای بارگیری این برنامه ساده ارسال می شود!

به هشدارهای پروژه در DevTools نگاهی بیندازید.

  • روی تب Console کلیک کنید.
  • مطمئن شوید که Warnings در قسمت کشویی سطوح در کنار ورودی Filter فعال باشد.

فیلتر هشدارها

  • به هشدار نمایش داده شده نگاهی بیندازید.

هشدار کنسول

Firebase که یکی از کتابخانه های مورد استفاده در این برنامه است، با ارائه اخطاری به توسعه دهندگان اطلاع می دهد که کل بسته آن را وارد نکنند، بلکه فقط اجزای مورد استفاده را وارد کنند. به عبارت دیگر، کتابخانه های استفاده نشده ای وجود دارد که می توان آنها را در این برنامه حذف کرد تا بارگذاری سریعتر آن انجام شود.

همچنین مواردی وجود دارد که از یک کتابخانه خاص استفاده می شود، اما ممکن است جایگزین ساده تری وجود داشته باشد. مفهوم حذف کتابخانه های غیر ضروری در ادامه این آموزش بررسی می شود.

تجزیه و تحلیل بسته نرم افزاری

دو وابستگی اصلی در برنامه وجود دارد:

  • Firebase : پلتفرمی است که تعدادی سرویس مفید برای iOS، Android یا برنامه های تحت وب ارائه می دهد. در اینجا پایگاه داده Realtime آن برای ذخیره و همگام سازی اطلاعات هر بچه گربه در زمان واقعی استفاده می شود.
  • Moment.js : یک کتابخانه ابزار که مدیریت تاریخ ها را در جاوا اسکریپت آسان تر می کند. تاریخ تولد هر بچه گربه در پایگاه داده Firebase ذخیره می شود و moment برای محاسبه سن آن در هفته استفاده می شود.

چگونه فقط دو وابستگی می توانند به اندازه یک بسته تقریباً 1 مگابایتی کمک کنند؟ خوب، یکی از دلایل این است که هر وابستگی به نوبه خود می تواند وابستگی های خاص خود را داشته باشد، بنابراین اگر هر عمق/شاخه از "درخت" وابستگی در نظر گرفته شود، خیلی بیشتر از دو مورد وجود دارد. اگر وابستگی های زیادی در آن گنجانده شود، بزرگ شدن نسبتاً سریع یک برنامه آسان است.

باندلر را تجزیه و تحلیل کنید تا ایده بهتری از آنچه در حال انجام است بدست آورید. تعدادی ابزار مختلف ساخته شده در جامعه وجود دارد که می تواند به انجام این کار کمک کند، مانند webpack-bundle-analyzer .

بسته این ابزار قبلاً به عنوان devDependency در برنامه گنجانده شده است.

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

این بدان معناست که می توان از آن به طور مستقیم در فایل پیکربندی وب پک استفاده کرد. آن را در همان ابتدای webpack.config.js وارد کنید:

const path = require("path");

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

اکنون آن را به عنوان یک افزونه در انتهای فایل در آرایه plugins اضافه کنید:

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

هنگامی که برنامه بارگیری مجدد می شود، به جای خود برنامه باید تصویری از کل بسته نرم افزاری را مشاهده کنید.

آنالایزر بسته نرم افزاری Webpack

نه به اندازه دیدن بعضی از بچه گربه ها 🐱، اما با این وجود فوق العاده مفید است. نگه داشتن ماوس روی هر یک از بسته ها اندازه آن را به سه شکل مختلف نشان می دهد:

اندازه آماری اندازه قبل از کوچک سازی یا فشرده سازی
اندازه تجزیه شده اندازه بسته واقعی در بسته نرم افزاری پس از کامپایل شدن. نسخه 4 وب پک (که در این برنامه استفاده می شود) فایل های کامپایل شده را به صورت خودکار کوچک می کند به همین دلیل این اندازه کوچکتر از اندازه آماری است.
اندازه Gzipped اندازه بسته پس از فشرده سازی با رمزگذاری gzip. این موضوع در یک راهنمای جداگانه پوشش داده شده است.

با ابزار webpack-bundle-analyzer، شناسایی بسته های استفاده نشده یا غیر ضروری که درصد زیادی از بسته را تشکیل می دهند آسان تر است.

حذف بسته های استفاده نشده

تجسم نشان می دهد که بسته firebase از یک پایگاه داده بسیار بیشتر تشکیل شده است. این شامل بسته های اضافی مانند:

  • firestore
  • auth
  • storage
  • messaging
  • functions

اینها همه خدمات شگفت انگیزی هستند که توسط Firebase ارائه می شوند (و برای کسب اطلاعات بیشتر به مستندات مراجعه کنید)، اما هیچ یک از آنها در برنامه استفاده نمی شود، بنابراین دلیلی برای وارد کردن همه آنها وجود ندارد.

برای مشاهده مجدد برنامه، تغییرات را در webpack.config.js برگردانید:

  • حذف BundleAnalyzerPlugin از لیست افزونه ها:
plugins: [
  //...
  new BundleAnalyzerPlugin()
];
  • و اکنون واردات استفاده نشده را از بالای فایل حذف کنید:
const path = require("path");

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

اکنون برنامه باید به طور معمول بارگیری شود. src/index.js را برای به‌روزرسانی واردات Firebase تغییر دهید.

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

اکنون هنگام بارگیری مجدد برنامه، هشدار DevTools نشان داده نمی شود. باز کردن پانل DevTools Network همچنین کاهش خوبی در اندازه بسته را نشان می دهد:

حجم بسته به 480 کیلوبایت کاهش یافت

بیش از نیمی از اندازه بسته حذف شد. Firebase خدمات مختلفی را ارائه می دهد و به توسعه دهندگان این امکان را می دهد که فقط مواردی را که واقعاً مورد نیاز هستند درج کنند. در این برنامه، فقط از firebase/database برای ذخیره و همگام سازی همه داده ها استفاده شده است. وارد کردن firebase/app ، که سطح API را برای هر یک از سرویس‌های مختلف تنظیم می‌کند، همیشه مورد نیاز است.

بسیاری از کتابخانه های محبوب دیگر، مانند lodash ، همچنین به توسعه دهندگان اجازه می دهند تا به طور انتخابی بخش های مختلف بسته های خود را وارد کنند. بدون انجام کار زیاد، به‌روزرسانی واردات کتابخانه در یک برنامه به گونه‌ای که فقط شامل موارد استفاده شده باشد، می‌تواند منجر به بهبود عملکرد قابل توجهی شود.

اگرچه اندازه باندل تا حدودی کاهش یافته است، هنوز کار بیشتری برای انجام دادن وجود دارد! 😈

حذف بسته های غیر ضروری

برخلاف Firebase، وارد کردن بخش‌هایی از کتابخانه moment را نمی‌توان به همین راحتی انجام داد، اما شاید بتوان آن را به طور کامل حذف کرد؟

تولد هر بچه گربه بامزه با فرمت یونیکس (میلی ثانیه) در پایگاه داده Firebase ذخیره می شود.

تاریخ تولد در قالب یونیکس ذخیره می شود

این یک مهر زمانی از یک تاریخ و زمان خاص است که با تعداد میلی‌ثانیه‌هایی که از 1 ژانویه 1970 ساعت 00:00 UTC سپری شده است نشان داده می‌شود. اگر بتوان تاریخ و زمان فعلی را در قالب یکسان محاسبه کرد، احتمالاً می توان یک تابع کوچک برای یافتن سن هر بچه گربه در هفته ایجاد کرد.

مثل همیشه سعی کنید همانطور که در اینجا دنبال می کنید کپی و پیست نکنید. با حذف moment از واردات در src/index.js شروع کنید.

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

شنونده رویداد Firebase وجود دارد که تغییرات مقدار را در پایگاه داده ما مدیریت می کند:

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

بالاتر از این، یک تابع کوچک برای محاسبه تعداد هفته ها از یک تاریخ معین اضافه کنید:

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

در این تابع، تفاوت در میلی ثانیه بین تاریخ و زمان فعلی (new Date).getTime() و تاریخ تولد (آگومان birthDate ، قبلاً بر حسب میلی ثانیه) محاسبه شده و بر تعداد میلی ثانیه در یک هفته تقسیم می شود.

در نهایت، تمام نمونه های moment را می توان در شنونده رویداد با استفاده از این تابع به جای آن حذف کرد:

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

اکنون برنامه را دوباره بارگیری کنید و یک بار دیگر به پنل شبکه نگاهی بیندازید.

حجم بسته به 225 کیلوبایت کاهش یافت

اندازه بسته ما دوباره بیش از نصف کاهش یافت!

نتیجه گیری

با این کد لبه، باید درک مناسبی از نحوه تجزیه و تحلیل یک بسته خاص داشته باشید و اینکه چرا حذف بسته های استفاده نشده یا غیر ضروری می تواند بسیار مفید باشد. قبل از شروع بهینه سازی یک برنامه با این تکنیک، مهم است که بدانید این امر در برنامه های بزرگتر می تواند بسیار پیچیده تر باشد .

با توجه به حذف کتابخانه های استفاده نشده ، سعی کنید دریابید که کدام بخش از یک بسته استفاده می شود و کدام بخش نه. برای بسته ای مرموز که به نظر می رسد در جایی استفاده نمی شود، یک قدم به عقب بردارید و بررسی کنید که کدام وابستگی های سطح بالا ممکن است به آن نیاز داشته باشند. سعی کنید راهی پیدا کنید که احتمالاً آنها را از یکدیگر جدا کنید.

وقتی نوبت به حذف کتابخانه‌های غیر ضروری می‌رسد، همه چیز می‌تواند کمی پیچیده‌تر باشد. این مهم است که از نزدیک با تیم خود کار کنید و ببینید آیا پتانسیلی برای ساده کردن بخش هایی از پایگاه کد وجود دارد یا خیر. حذف moment در این برنامه ممکن است به نظر کار درستی باشد که هر بار انجام شود، اما اگر مناطق زمانی و مناطق مختلف وجود داشته باشد که نیاز به مدیریت داشته باشند، چه؟ یا اگر دستکاری های پیچیده تری در تاریخ وجود داشته باشد چه می شود؟ هنگام دستکاری و تجزیه تاریخ/زمان‌ها، همه چیز می‌تواند بسیار مشکل باشد، و کتابخانه‌هایی مانند moment و date-fns این امر را به‌طور قابل توجهی ساده می‌کنند.

همه چیز یک مبادله است، و این مهم است که بسنجیم که آیا ارزش پیچیدگی و تلاش برای ارائه یک راه حل سفارشی به جای تکیه بر یک کتابخانه شخص ثالث را دارد یا خیر.