با مهاجرت به Firebase JS SDK مدولار، برنامه وب خود را شارژ کنید

۱. قبل از شروع

کیت توسعه نرم‌افزاری ماژولار Firebase JS، بازنویسی کیت توسعه نرم‌افزاری JS موجود است و به عنوان نسخه اصلی بعدی منتشر خواهد شد. این کیت به توسعه‌دهندگان امکان می‌دهد کدهای استفاده نشده را از کیت توسعه نرم‌افزاری Firebase JS حذف کنند تا بسته‌های کوچک‌تری ایجاد کنند و به عملکرد بهتری دست یابند.

قابل توجه‌ترین تفاوت در SDK ماژولار JS این است که ویژگی‌ها اکنون در توابع شناور آزاد سازماندهی شده‌اند که شما آنها را وارد خواهید کرد، برخلاف یک فضای نام واحد firebase که شامل همه چیز می‌شود. این روش جدید سازماندهی کد، امکان tree shake را فراهم می‌کند و شما یاد خواهید گرفت که چگونه هر برنامه‌ای را که در حال حاضر از SDK JS نسخه ۸ Firebase استفاده می‌کند، به نسخه ماژولار جدید ارتقا دهید.

برای ارائه یک فرآیند ارتقاء روان، مجموعه‌ای از بسته‌های سازگاری ارائه شده است. در این آزمایشگاه کد، یاد خواهید گرفت که چگونه از بسته‌های سازگاری برای پورت کردن برنامه به صورت قطعه قطعه استفاده کنید.

آنچه خواهید ساخت

در این آزمایشگاه کد، شما به تدریج یک برنامه وب فهرست پیگیری سهام موجود که از v8 JS SDK استفاده می‌کند را در سه مرحله به JS SDK ماژولار جدید منتقل خواهید کرد:

  • برای استفاده از بسته‌های سازگاری، برنامه را ارتقا دهید
  • برنامه را از بسته‌های سازگاری به API ماژولار، قطعه قطعه ارتقا دهید.
  • برای بهبود بیشتر عملکرد برنامه، از Firestore Lite، یک پیاده‌سازی سبک از Firestore SDK، استفاده کنید.

2d351cb47b604ad7.png

این آزمایشگاه کد بر ارتقاء SDK فایربیس تمرکز دارد. سایر مفاهیم و بلوک‌های کد به طور خلاصه توضیح داده شده‌اند و برای کپی و پیست ساده در اختیار شما قرار گرفته‌اند.

آنچه نیاز دارید

  • یک مرورگر دلخواه مثل کروم
  • IDE/ویرایشگر متن مورد نظر شما، مانند WebStorm ، Atom ، Sublime یا VS Code
  • مدیر بسته npm که معمولاً با Node.js همراه است
  • نمونه کد codelab (برای نحوه دریافت کد به مرحله بعدی codelab مراجعه کنید.)

۲. آماده شوید

کد را دریافت کنید

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

مخزن گیت‌هاب codelab را از خط فرمان کلون کنید:

git clone https://github.com/FirebaseExtended/codelab-modular-sdk.git

از طرف دیگر، اگر git را نصب ندارید، می‌توانید مخزن را به صورت یک فایل ZIP دانلود کنید و فایل zip دانلود شده را از حالت فشرده خارج کنید.

برنامه را وارد کنید

  1. با استفاده از IDE خود، پوشه codelab-modular-sdk را باز یا ایمپورت کنید.
  2. برای نصب وابستگی‌های مورد نیاز برای ساخت و اجرای برنامه به صورت محلی، npm install اجرا کنید.
  3. برای ساخت برنامه، npm run build اجرا کنید.
  4. برای شروع وب سرور، npm run serve اجرا کنید.
  5. یک تب مرورگر را باز کنید و به آدرس http://localhost:8080 بروید.

71a8a7d47392e8f4.png

۳. یک خط پایه ایجاد کنید

نقطه شروع شما چیست؟

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

مطمئن شوید که همه چیز در برنامه کار می‌کند:

  1. با استفاده از دکمه ورود در گوشه بالا سمت راست، به صورت ناشناس وارد شوید.
  2. پس از ورود به سیستم، با کلیک روی دکمه افزودن ، تایپ حروف و کلیک روی ردیف نتایج جستجو که در زیر ظاهر می‌شود، «NFLX»، «SBUX» و «T» را جستجو و به لیست تماشا اضافه کنید.
  3. با کلیک روی x در انتهای ردیف، یک سهم را از فهرست پیگیری حذف کنید.
  4. به‌روزرسانی‌های لحظه‌ای قیمت سهام را تماشا کنید.
  5. Chrome DevTools را باز کنید، به تب Network بروید و گزینه Disable cache و Use large request rows را تیک بزنید. Disable cache باعث می‌شود که همیشه آخرین تغییرات را پس از رفرش دریافت کنیم و Use large request rows باعث می‌شود که ردیف، هم اندازه منتقل شده و هم اندازه منبع را برای یک منبع نمایش دهد. در این آزمایشگاه کد، ما عمدتاً به اندازه main.js علاقه‌مند هستیم.

48a096debb2aa940.png

  1. برنامه را تحت شرایط مختلف شبکه با استفاده از شبیه‌سازی گلوگاه شبکه بارگذاری کنید. شما از Slow 3G برای اندازه‌گیری زمان بارگذاری در این آزمایشگاه کد استفاده خواهید کرد زیرا در این حالت، اندازه بسته کوچک‌تر بیشترین کمک را می‌کند.

4397cb2c1327089.png

حالا شروع کنید و مهاجرت برنامه به API ماژولار جدید را آغاز کنید.

۴. از بسته‌های سازگاری استفاده کنید

بسته‌های سازگاری به شما امکان می‌دهند بدون تغییر یکباره تمام کد Firebase، به نسخه جدید SDK ارتقا دهید. می‌توانید آنها را به تدریج به API ماژولار ارتقا دهید.

در این مرحله، کتابخانه Firebase را از نسخه ۸ به نسخه جدید ارتقا می‌دهید و کد را برای استفاده از بسته‌های سازگاری تغییر می‌دهید. در مراحل بعدی، یاد خواهید گرفت که ابتدا فقط کد Firebase Auth را برای استفاده از API ماژولار ارتقا دهید، سپس کد Firestore را ارتقا دهید.

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

SDK جدید را دریافت کنید

بخش وابستگی‌ها را در package.json پیدا کنید و آن را با موارد زیر جایگزین کنید:

بسته.json

"dependencies": {
    "firebase": "^9.0.0" 
}

وابستگی‌ها را دوباره نصب کنید

از آنجایی که نسخه وابستگی را تغییر داده‌ایم، باید npm install دوباره اجرا کنیم تا نسخه جدید وابستگی را دریافت کنیم.

تغییر مسیرهای واردات

بسته‌های سازگاری تحت زیرماژول firebase/compat قرار دارند، بنابراین مسیرهای واردات را بر این اساس به‌روزرسانی خواهیم کرد:

  1. به فایل src/firebase.ts بروید
  2. ایمپورت‌های موجود را با ایمپورت‌های زیر جایگزین کنید:

src/firebase.ts

import firebase from 'firebase/compat/app'; 
import 'firebase/compat/auth'; 
import 'firebase/compat/firestore';

تأیید کنید که برنامه کار می‌کند

  1. برای بازسازی برنامه، npm run build اجرا کنید.
  2. یک تب مرورگر را باز کنید و به آدرس http://localhost:8080 بروید ، یا تب موجود را رفرش کنید.
  3. با برنامه کار کنید. همه چیز هنوز باید کار کند.

۵. Auth را برای استفاده از API ماژولار ارتقا دهید

شما می‌توانید محصولات Firebase را به هر ترتیبی ارتقا دهید. در این آزمایشگاه کد، ابتدا Auth را ارتقا می‌دهید تا مفاهیم اولیه را یاد بگیرید زیرا Auth API نسبتاً ساده است. ارتقای Firestore کمی پیچیده‌تر است و در ادامه یاد خواهید گرفت که چگونه این کار را انجام دهید.

به‌روزرسانی مقداردهی اولیه Auth

  1. به فایل src/firebase.ts بروید
  2. ایمپورت زیر را اضافه کنید:

src/firebase.ts

import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
  1. import 'firebase/compat/auth'.
  2. به جای export const firebaseAuth = app.auth(); ‎ عبارت زیر را قرار دهید:

src/firebase.ts

export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
  1. export type User = firebase.User; را در انتهای فایل حذف کنید. User مستقیماً در src/auth.ts که در مرحله بعد تغییر خواهید داد، خروجی گرفته خواهد شد.

کد تأیید را به‌روزرسانی کنید

  1. به فایل src/auth.ts بروید
  2. ایمپورت‌های زیر را به بالای فایل اضافه کنید:

src/auth.ts

import { 
    signInAnonymously, 
    signOut,
    onAuthStateChanged,
    User
} from 'firebase/auth';
  1. از آنجایی که شما قبلاً User از 'firebase/auth'. وارد کرده‌اید، User از import { firebaseAuth, User } from './firebase'; حذف کنید.
  2. توابع را برای استفاده از API ماژولار به‌روزرسانی کنید.

همانطور که قبلاً هنگام به‌روزرسانی دستور import مشاهده کردید، بسته‌ها در نسخه ۹ بر خلاف APIهای نسخه ۸ که مبتنی بر فضای نام و الگوی سرویس زنجیره‌ای نقطه‌ای هستند، حول توابعی سازماندهی شده‌اند که می‌توانید وارد کنید. این سازماندهی جدید کد است که امکان treeshaking کدهای استفاده نشده را فراهم می‌کند، زیرا به ابزارهای ساخت اجازه می‌دهد تا تجزیه و تحلیل کنند که کدام کد استفاده شده و کدام نشده است.

در نسخه ۹، سرویس‌ها به عنوان اولین آرگومان به توابع ارسال می‌شوند. سرویس‌ها اشیایی هستند که شما از مقداردهی اولیه یک سرویس Firebase دریافت می‌کنید، مثلاً شیء برگردانده شده از getAuth() یا initializeAuth() . آن‌ها وضعیت یک سرویس Firebase خاص را نگه می‌دارند و تابع از وضعیت برای انجام وظایف خود استفاده می‌کند. بیایید این الگو را برای پیاده‌سازی توابع زیر اعمال کنیم:

src/auth.ts

export function firebaseSignInAnonymously() { 
    return signInAnonymously(firebaseAuth); 
} 

export function firebaseSignOut() { 
    return signOut(firebaseAuth); 
} 

export function onUserChange(callback: (user: User | null) => void) { 
    return onAuthStateChanged(firebaseAuth, callback); 
} 

export { User } from 'firebase/auth';

تأیید کنید که برنامه کار می‌کند

  1. برای بازسازی برنامه، npm run build اجرا کنید.
  2. یک تب مرورگر را باز کنید و به آدرس http://localhost:8080 بروید ، یا تب موجود را رفرش کنید.
  3. با برنامه کار کنید. همه چیز هنوز باید کار کند.

اندازه بسته را بررسی کنید

  1. ابزارهای توسعه کروم را باز کنید.
  2. به برگه شبکه بروید.
  3. برای دریافت درخواست‌های شبکه، صفحه را رفرش کنید.
  4. به دنبال فایل main.js بگردید و حجم آن را بررسی کنید. شما حجم بسته را ۱۰۰ کیلوبایت (۳۶ کیلوبایت فشرده شده با gzip) کاهش داده‌اید، یا با تغییر تنها چند خط کد، حدود ۲۲٪ کوچکتر شده است! سایت همچنین با اتصال کند ۳G، ۰.۷۵ ثانیه سریعتر بارگیری می‌شود.

2e4eafaf66cd829b.png

۶. اپلیکیشن فایربیس و فایراستور را برای استفاده از API ماژولار ارتقا دهید

مقداردهی اولیه فایربیس را به‌روزرسانی کنید

  1. به فایل src/firebase.ts.
  2. دستور import firebase from 'firebase/compat/app'; را با دستور زیر جایگزین کنید:

src/firebase.ts

import { initializeApp } from 'firebase/app';
  1. به جای const app = firebase.initializeApp({...}); دستور زیر را قرار دهید:

src/firebase.ts

const app = initializeApp({
    apiKey: "AIzaSyBnRKitQGBX0u8k4COtDTILYxCJuMf7xzE", 
    authDomain: "exchange-rates-adcf6.firebaseapp.com", 
    databaseURL: "https://exchange-rates-adcf6.firebaseio.com", 
    projectId: "exchange-rates-adcf6", 
    storageBucket: "exchange-rates-adcf6.firebasestorage.app", 
    messagingSenderId: "875614679042", 
    appId: "1:875614679042:web:5813c3e70a33e91ba0371b"
});

به‌روزرسانی مقداردهی اولیه Firestore

  1. در همان فایل src/firebase.ts, import 'firebase/compat/firestore'; ‎ را با ‎'‎ جایگزین کنید.

src/firebase.ts

import { getFirestore } from 'firebase/firestore';
  1. به جای export const firestore = app.firestore(); ‎ عبارت زیر را قرار دهید:

src/firebase.ts

export const firestore = getFirestore();
  1. تمام خطوط بعد از " export const firestore = ... " را حذف کنید.

به‌روزرسانی واردات

  1. فایل src/services.ts.
  2. FirestoreFieldPath ، FirestoreFieldValue و QuerySnapshot را از ایمپورت حذف کنید. ایمپورت از './firebase' اکنون باید به شکل زیر باشد:

src/services.ts

import { firestore } from './firebase';
  1. توابع و انواعی را که قرار است استفاده کنید، در بالای فایل وارد کنید:
    **src/services.ts**
import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove, 
    onSnapshot, 
    query, 
    where, 
    documentId, 
    QuerySnapshot
} from 'firebase/firestore';
  1. یک ارجاع به مجموعه‌ای که شامل همه تیکرها است ایجاد کنید:

src/services.ts

const tickersCollRef = collection(firestore, 'current');
  1. از getDocs() برای دریافت تمام اسناد از مجموعه استفاده کنید:

src/services.ts

const tickers = await getDocs(tickersCollRef);

برای کد نهایی search() مراجعه کنید.

به‌روزرسانی addToWatchList()

از doc() برای ایجاد یک ارجاع سند به فهرست پیگیری کاربر استفاده کنید، سپس با استفاده setDoc() به همراه arrayUnion() یک نشانگر به آن اضافه کنید:

src/services.ts

export function addToWatchList(ticker: string, user: User) {
      const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
      return setDoc(watchlistRef, {
       tickers: arrayUnion(ticker)
   }, { merge: true });
}

به‌روزرسانی تابع deleteFromWatchList()‎

به طور مشابه، با استفاده از setDoc() به همراه arrayRemove() یک تیکر را از لیست پیگیری کاربر حذف کنید:

src/services.ts

export function deleteFromWatchList(ticker: string, user: User) {
   const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
   return setDoc(watchlistRef, {
       tickers: arrayRemove(ticker)
   }, { merge: true });
}

به‌روزرسانی subscribeToTickerChanges()

  1. ابتدا از doc() برای ایجاد یک ارجاع سند به فهرست پیگیری کاربر استفاده کنید، سپس با استفاده از onSnapshot() به تغییرات فهرست پیگیری گوش دهید:

src/services.ts

const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
   /* subscribe to ticker price changes */
});
  1. وقتی تیکرها را در لیست پیگیری قرار دادید، query() برای ایجاد یک کوئری جهت دریافت قیمت‌های آنها استفاده کنید و onSnapshot() برای گوش دادن به تغییرات قیمت آنها استفاده کنید:

src/services.ts

const priceQuery = query(
    collection(firestore, 'current'),
    where(documentId(), 'in', tickers)
);
unsubscribePrevTickerChanges = onSnapshot(priceQuery, snapshot => {
               if (firstload) {
                   performance && performance.measure("initial-data-load");
                   firstload = false;
                   logPerformance();
               }
               const stocks = formatSDKStocks(snapshot);
               callback(stocks);
  });

برای پیاده‌سازی کامل، به subscribeToTickerChanges() مراجعه کنید.

به‌روزرسانی subscribeToAllTickerChanges()

ابتدا collection() برای ایجاد یک ارجاع به مجموعه‌ای که شامل قیمت‌های همه تیکرهاست استفاده می‌کنید، سپس onSnapshot() برای گوش دادن به تغییرات قیمت استفاده خواهید کرد:

src/services.ts

export function subscribeToAllTickerChanges(callback: TickerChangesCallBack) {
   const tickersCollRef = collection(firestore, 'current');
   return onSnapshot(tickersCollRef, snapshot => {
       if (firstload) {
           performance && performance.measure("initial-data-load");
           firstload = false;
           logPerformance();
       }
       const stocks = formatSDKStocks(snapshot);
       callback(stocks);
   });
}

تأیید کنید که برنامه کار می‌کند

  1. برای بازسازی برنامه، npm run build اجرا کنید.
  2. یک تب مرورگر را باز کنید و به آدرس http://localhost:8080 بروید ، یا تب موجود را رفرش کنید.
  3. با برنامه کار کنید. همه چیز هنوز باید کار کند.

اندازه بسته را بررسی کنید

  1. ابزارهای توسعه کروم را باز کنید.
  2. به برگه شبکه بروید.
  3. برای دریافت درخواست‌های شبکه، صفحه را رفرش کنید.
  4. به دنبال main.js بگردید و حجم آن را بررسی کنید. دوباره آن را با حجم اولیه بسته مقایسه کنید - ما حجم بسته را بیش از ۲۰۰ کیلوبایت (۶۳.۸ کیلوبایت با فشرده‌سازی gzip) یا ۵۰٪ کوچکتر کاهش داده‌ایم که به معنی ۱.۳ ثانیه زمان بارگذاری سریع‌تر است!

7660cdc574ee8571.png

۷. از Firestore Lite برای سرعت بخشیدن به رندر اولیه صفحه استفاده کنید

فایر استور لایت چیست؟

کیت توسعه نرم‌افزار Firestore قابلیت‌های ذخیره‌سازی پیچیده، پخش زنده، ذخیره‌سازی پایدار، همگام‌سازی آفلاین چند تبی، تلاش‌های مجدد، همزمانی خوش‌بینانه و موارد بسیار دیگری را ارائه می‌دهد و به همین دلیل حجم بسیار زیادی دارد. اما ممکن است بخواهید داده‌ها را یک بار و بدون نیاز به هیچ یک از ویژگی‌های پیشرفته دریافت کنید. برای این موارد، Firestore یک راه‌حل ساده و سبک، یک بسته کاملاً جدید - Firestore Lite - ایجاد کرده است.

یکی از کاربردهای عالی Firestore Lite بهینه‌سازی عملکرد رندر اولیه صفحه است، جایی که فقط باید بدانید که آیا کاربر وارد سیستم شده است یا خیر، سپس برخی از داده‌ها را از Firetore برای نمایش بخوانید.

در این مرحله، یاد خواهید گرفت که چگونه از Firestore lite برای کاهش حجم بسته نرم‌افزاری استفاده کنید تا سرعت رندر اولیه صفحه افزایش یابد، سپس SDK اصلی Firestore را به صورت پویا بارگذاری کنید تا در به‌روزرسانی‌های بلادرنگ مشترک شوید.

شما کد را به صورت زیر ریفکتور خواهید کرد:

  1. سرویس‌های بلادرنگ را به یک فایل جداگانه منتقل کنید تا بتوان آن‌ها را با استفاده از واردات پویا به صورت پویا بارگذاری کرد.
  2. توابع جدیدی برای استفاده از Firestore Lite جهت بازیابی فهرست پیگیری و قیمت سهام ایجاد کنید.
  3. از توابع جدید Firestore Lite برای بازیابی داده‌ها جهت رندر اولیه صفحه استفاده کنید، سپس سرویس‌های بلادرنگ را به صورت پویا بارگذاری کنید تا به به‌روزرسانی‌های بلادرنگ گوش دهند.

انتقال سرویس‌های بلادرنگ به یک فایل جدید

  1. یک فایل جدید به نام src/services.realtime.ts.
  2. توابع subscribeToTickerChanges() و subscribeToAllTickerChanges() را از src/services.ts به فایل جدید منتقل کنید.
  3. موارد ضروری را به بالای فایل جدید اضافه کنید.

شما هنوز باید چند تغییر در اینجا ایجاد کنید:

  1. ابتدا، یک نمونه Firestore از Firestore SDK اصلی در بالای فایل ایجاد کنید تا در توابع استفاده شود. شما نمی‌توانید نمونه Firestore را از firebase.ts در اینجا وارد کنید زیرا قرار است آن را در چند مرحله به یک نمونه Firestore Lite تغییر دهید که فقط برای رندر اولیه صفحه استفاده خواهد شد.
  2. دوم، از شر متغیر firstload و بلوک if که توسط آن محافظت می‌شود خلاص شوید. قابلیت‌های آنها به توابع جدیدی که در مرحله بعدی ایجاد خواهید کرد، منتقل می‌شوند.

src/services.realtime.ts

import { User } from './auth'
import { TickerChange } from './models';
import { collection, doc, onSnapshot, query, where, documentId, getFirestore } from 'firebase/firestore';
import { formatSDKStocks } from './services';

const firestore = getFirestore();
type TickerChangesCallBack = (changes: TickerChange[]) => void

export function subscribeToTickerChanges(user: User, callback: TickerChangesCallBack) {

   let unsubscribePrevTickerChanges: () => void;

   // Subscribe to watchlist changes. We will get an update whenever a ticker is added/deleted to the watchlist
   const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
   const unsubscribe = onSnapshot(watchlistRef, snapshot => {
       const doc = snapshot.data();
       const tickers = doc ? doc.tickers : [];

       if (unsubscribePrevTickerChanges) {
           unsubscribePrevTickerChanges();
       }

       if (tickers.length === 0) {
           callback([]);
       } else {
           // Query to get current price for tickers in the watchlist
           const priceQuery = query(
               collection(firestore, 'current'),
               where(documentId(), 'in', tickers)
           );

           // Subscribe to price changes for tickers in the watchlist
           unsubscribePrevTickerChanges = onSnapshot(priceQuery, snapshot => {
               const stocks = formatSDKStocks(snapshot);
               callback(stocks);
           });
       }
   });
   return () => {
       if (unsubscribePrevTickerChanges) {
           unsubscribePrevTickerChanges();
       }
       unsubscribe();
   };
}

export function subscribeToAllTickerChanges(callback: TickerChangesCallBack) {
   const tickersCollRef = collection(firestore, 'current');
   return onSnapshot(tickersCollRef, snapshot => {
       const stocks = formatSDKStocks(snapshot);
       callback(stocks);
   });
}

برای دریافت داده‌ها از Firestore lite استفاده کنید

  1. src/services.ts.
  2. مسیر ایمپورت را از 'firebase/firestore' به 'firebase/firestore/lite', getDoc اضافه کنید و onSnapshot از لیست ایمپورت حذف کنید :

src/services.ts

import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove,
//  onSnapshot, // firestore lite doesn't support realtime updates
    query, 
    where, 
    documentId, 
    QuerySnapshot, 
    getDoc // add this import
} from 'firebase/firestore/lite';
  1. توابعی را برای دریافت داده‌های مورد نیاز برای رندر اولیه صفحه با استفاده از Firestore Lite اضافه کنید:

src/services.ts

export async function getTickerChanges(tickers: string[]): Promise<TickerChange[]> {

   if (tickers.length === 0) {
       return [];
   }

   const priceQuery = query(
       collection(firestore, 'current'),
       where(documentId(), 'in', tickers)
   );
   const snapshot = await getDocs(priceQuery);
   performance && performance.measure("initial-data-load");
   logPerformance();
   return formatSDKStocks(snapshot);
}

export async function getTickers(user: User): Promise<string[]> {
   const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
   const data =  (await getDoc(watchlistRef)).data();

   return data ? data.tickers : [];
}

export async function getAllTickerChanges(): Promise<TickerChange[]> {
   const tickersCollRef = collection(firestore, 'current');
   const snapshot = await getDocs(tickersCollRef);
   performance && performance.measure("initial-data-load");
   logPerformance();
   return formatSDKStocks(snapshot);
}
  1. src/firebase.ts را باز کنید و مسیر ایمپورت را از 'firebase/firestore' به 'firebase/firestore/lite':

src/firebase.ts

import { getFirestore } from 'firebase/firestore/lite';

همه آنها را به هم گره بزنید

  1. src/main.ts.
  2. شما به توابع تازه ایجاد شده برای دریافت داده‌ها برای رندر اولیه صفحه و چند تابع کمکی برای مدیریت وضعیت برنامه نیاز خواهید داشت. بنابراین اکنون importها را به‌روزرسانی کنید:

src/main.ts

import { renderLoginPage, renderUserPage } from './renderer';
import { getAllTickerChanges, getTickerChanges, getTickers } from './services';
import { onUserChange } from './auth';
import { getState, setRealtimeServicesLoaded, setUser } from './state';
import './styles.scss';
  1. با استفاده از یک ایمپورت پویا در بالای فایل src/services.realtime را بارگذاری کنید. متغیر loadRealtimeService یک promise است که پس از بارگذاری کد، با سرویس‌های بلادرنگ حل می‌شود. بعداً از آن برای اشتراک در به‌روزرسانی‌های بلادرنگ استفاده خواهید کرد.

src/main.ts

const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
   setRealtimeServicesLoaded(true);
});
  1. تابع فراخوانی onUserChange() را به یک تابع async تغییر دهید تا بتوانیم await در بدنه تابع استفاده کنیم:

src/main.ts

onUserChange(async user => {
 // callback body
});
  1. حالا داده‌ها را برای رندر اولیه صفحه با استفاده از توابع جدیدی که در مرحله قبل ایجاد کردیم، دریافت کنید.

در تابع فراخوانی onUserChange() ، شرط if را در جایی که کاربر وارد سیستم شده است پیدا کنید و کد را داخل عبارت if کپی و جایگذاری کنید:

src/main.ts

onUserChange(async user => {
      // LEAVE THE EXISTING CODE UNCHANGED HERE
      ...

      if (user) {
       // REPLACE THESE LINES

       // user page
       setUser(user);

       // show loading screen in 500ms
       const timeoutId = setTimeout(() => {
           renderUserPage(user, {
               loading: true,
               tableData: []
           });
       }, 500);

       // get data once if realtime services haven't been loaded
       if (!getState().realtimeServicesLoaded) {
           const tickers = await getTickers(user);
           const tickerData = await getTickerChanges(tickers);
           clearTimeout(timeoutId);
           renderUserPage(user, { tableData: tickerData });
       }

       // subscribe to realtime updates once realtime services are loaded
       loadRealtimeService.then(({ subscribeToTickerChanges }) => {
           unsubscribeTickerChanges = subscribeToTickerChanges(user, stockData => {
               clearTimeout(timeoutId);
               renderUserPage(user, { tableData: stockData })
           });
       });
   } else {
     // DON'T EDIT THIS PART, YET   
   }
}
  1. در بلوک else که هیچ کاربری وارد سیستم نشده است، اطلاعات قیمت همه سهام را با استفاده از firestore lite دریافت کنید، صفحه را رندر کنید، سپس پس از بارگذاری سرویس‌های بلادرنگ، به تغییرات قیمت گوش دهید:

src/main.ts

if (user) {
   // DON'T EDIT THIS PART, WHICH WE JUST CHANGED ABOVE
   ...
} else {
   // REPLACE THESE LINES

   // login page
   setUser(null);

   // show loading screen in 500ms
   const timeoutId = setTimeout(() => {
       renderLoginPage('Landing page', {
           loading: true,
           tableData: []
       });
   }, 500);

   // get data once if realtime services haven't been loaded
   if (!getState().realtimeServicesLoaded) {
       const tickerData = await getAllTickerChanges();
       clearTimeout(timeoutId);
       renderLoginPage('Landing page', { tableData: tickerData });
   }

   // subscribe to realtime updates once realtime services are loaded
   loadRealtimeService.then(({ subscribeToAllTickerChanges }) => {
       unsubscribeAllTickerChanges = subscribeToAllTickerChanges(stockData => {
           clearTimeout(timeoutId);
           renderLoginPage('Landing page', { tableData: stockData })
       });
   });
}

برای کد نهایی به src/main.ts مراجعه کنید.

تأیید کنید که برنامه کار می‌کند

  1. برای بازسازی برنامه، npm run build اجرا کنید.
  2. یک تب مرورگر را باز کنید و به آدرس http://localhost:8080 بروید ، یا تب موجود را رفرش کنید.

اندازه بسته را بررسی کنید

  1. ابزار توسعه کروم را باز کنید.
  2. به برگه شبکه بروید.
  3. برای دریافت درخواست‌های شبکه، صفحه را رفرش کنید
  4. به دنبال main.js بگردید و حجم آن را بررسی کنید.
  5. حالا فقط ۱۱۵ کیلوبایت (۳۴.۵ کیلوبایت با gzip) حجم دارد. این ۷۵٪ کمتر از حجم اولیه بسته است که ۴۴۶ کیلوبایت (۱۳۸ کیلوبایت با gzip) بود! در نتیجه، سایت با اتصال ۳G بیش از ۲ ثانیه سریع‌تر بارگیری می‌شود - یک بهبود عالی در عملکرد و تجربه کاربری!

9ea7398a8c8ef81b.png

۸. تبریک

تبریک می‌گویم، شما با موفقیت برنامه را ارتقا دادید و آن را کوچک‌تر و سریع‌تر کردید!

شما از بسته‌های compat برای ارتقای قطعه به قطعه برنامه استفاده کردید، و از Firestore Lite برای سرعت بخشیدن به رندر اولیه صفحه استفاده کردید، سپس Firestore اصلی را به صورت پویا بارگذاری کردید تا تغییرات قیمت را پخش کنید.

شما همچنین در طول این آزمایش کد، اندازه بسته را کاهش داده و زمان بارگذاری آن را بهبود بخشیده‌اید:

فایل اصلی.js

اندازه منبع (کیلوبایت)

حجم gzip شده (کیلوبایت)

زمان بارگذاری (ثانیه) (روی سرعت پایین 3G)

نسخه ۸

۴۴۶

۱۳۸

۴.۹۲

سازگار با نسخه ۹

۴۲۹

۱۲۴

۴.۶۵

فقط نسخه ۹ ماژولار

۳۴۸

۱۰۲

۴.۲

نسخه ۹ کاملاً ماژولار

۲۴۴

۷۴.۶

۳.۶۶

نسخه ۹ کاملاً ماژولار + فایراستور لایت

۱۱۷

۳۴.۹

۲.۸۸

32a71bd5a774e035.png

اکنون مراحل کلیدی مورد نیاز برای ارتقاء یک برنامه وب که از نسخه ۸ Firebase JS SDK استفاده می‌کند به SDK JS ماژولار جدید را می‌دانید.

مطالعه بیشتر

اسناد مرجع