เพิ่มพลังให้กับเว็บแอปของคุณโดยการย้ายไปยัง Firebase JS SDK แบบโมดูลาร์

1. ก่อนที่คุณจะเริ่ม

โมดูลาร์ Firebase JS SDK เป็นการเขียนใหม่ของ JS SDK ที่มีอยู่ และจะเปิดตัวเป็นเวอร์ชันหลักถัดไป ช่วยให้นักพัฒนาสามารถแยกโค้ดที่ไม่ได้ใช้ออกจาก Firebase JS SDK เพื่อสร้างบันเดิลขนาดเล็กลงและมีประสิทธิภาพดีขึ้น

ความแตกต่างที่เห็นได้ชัดเจนที่สุดในโมดูลาร์ JS SDK คือตอนนี้ฟีเจอร์ต่างๆ ได้รับการจัดระเบียบในฟังก์ชันลอยตัวฟรีที่คุณจะนำเข้า ซึ่งต่างจากเนมสเปซ firebase เดียวที่รวมทุกอย่างไว้ วิธีใหม่ในการจัดระเบียบโค้ดคือสิ่งที่ทำให้เกิดการเขย่าแบบทรี และคุณจะได้เรียนรู้วิธีอัปเกรดแอปใดๆ ที่ใช้ Firebase JS SDK เวอร์ชัน 8 ในปัจจุบันเป็นแอปแบบโมดูลาร์ใหม่

เพื่อให้กระบวนการอัปเกรดราบรื่น จึงมีการจัดเตรียมชุดแพ็คเกจความเข้ากันได้ไว้ ใน Codelab นี้ คุณจะได้เรียนรู้วิธีใช้แพ็คเกจความเข้ากันได้เพื่อย้ายแอปทีละชิ้น

สิ่งที่คุณจะสร้าง

ใน Codelab นี้ คุณจะค่อยๆ ย้ายเว็บแอปรายการเฝ้าดูหุ้นที่มีอยู่ซึ่งใช้ v8 JS SDK ไปยัง JS SDK แบบโมดูลาร์ใหม่ในสามขั้นตอน:

  • อัปเกรดแอปเพื่อใช้แพ็คเกจความเข้ากันได้
  • อัปเกรดแอปจากแพ็คเกจความเข้ากันได้เป็น API แบบโมดูลาร์ทีละชิ้น
  • ใช้ Firestore Lite ซึ่งเป็นการนำ Firestore SDK ไปใช้เพียงเล็กน้อย เพื่อปรับปรุงประสิทธิภาพของแอปให้ดียิ่งขึ้น

2d351cb47b604ad7.png

Codelab นี้มุ่งเน้นไปที่การอัปเกรด Firebase SDK แนวคิดและบล็อคโค้ดอื่นๆ จะถูกกลบทับไว้และมีไว้ให้คุณคัดลอกและวางได้อย่างง่ายดาย

สิ่งที่คุณต้องการ

  • เบราว์เซอร์ที่คุณเลือก เช่น Chrome
  • โปรแกรมแก้ไข IDE/ข้อความที่คุณเลือก เช่น WebStorm , Atom , Sublime หรือ VS Code
  • ตัวจัดการแพ็คเกจ npm ซึ่งโดยทั่วไปจะมาพร้อมกับ Node.js
  • โค้ดตัวอย่างของ Codelab (ดูวิธีรับโค้ดในขั้นตอนถัดไปของ Codelab)

2. ตั้งค่า

รับรหัส

ทุกสิ่งที่คุณต้องการสำหรับโปรเจ็กต์นี้อยู่ใน repo Git ในการเริ่มต้น คุณจะต้องคว้าโค้ดและเปิดมันในสภาพแวดล้อมการพัฒนาที่คุณชื่นชอบ

โคลน ที่เก็บ Github ของ 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

3. สร้างพื้นฐาน

จุดเริ่มต้นของคุณคืออะไร?

จุดเริ่มต้นของคุณคือแอปเฝ้าดูหุ้นที่ออกแบบมาสำหรับ Codelab นี้ โค้ดได้รับการปรับให้ง่ายขึ้นเพื่อแสดงแนวคิดใน Codelab นี้ และมีการจัดการข้อผิดพลาดเพียงเล็กน้อย หากคุณเลือกที่จะใช้โค้ดใดๆ นี้ซ้ำในแอปที่ใช้งานจริง ตรวจสอบให้แน่ใจว่าคุณจัดการกับข้อผิดพลาดใดๆ และทดสอบโค้ดทั้งหมดอย่างสมบูรณ์

ตรวจสอบให้แน่ใจว่าทุกอย่างใช้งานได้ในแอป:

  1. เข้าสู่ระบบโดยไม่ระบุชื่อโดยใช้ปุ่ม เข้าสู่ระบบ ที่มุมขวาบน
  2. หลังจากเข้าสู่ระบบ ให้ค้นหาและเพิ่ม "NFLX", "SBUX" และ "T" ลงในรายการเฝ้าดูโดยคลิกปุ่ม เพิ่ม พิมพ์ตัวอักษร และคลิกแถวผลการค้นหาที่ปรากฏขึ้นด้านล่าง
  3. ลบหุ้นออกจากรายการเฝ้าดูโดยคลิก x ที่ท้ายแถว
  4. ชมการอัพเดตราคาหุ้นแบบเรียลไทม์
  5. เปิด Chrome DevTools ไปที่แท็บ เครือข่าย แล้วทำเครื่องหมายที่ ปิดใช้งานแคช และ ใช้แถวคำขอขนาดใหญ่ ปิดใช้งานแคช ทำให้แน่ใจว่าเราได้รับการเปลี่ยนแปลงล่าสุดเสมอหลังจากการรีเฟรช และ การใช้แถวคำขอขนาดใหญ่ ทำให้แถวแสดงทั้งขนาดที่ส่งและขนาดทรัพยากรสำหรับทรัพยากร ใน Codelab นี้ เราสนใจขนาดของ main.js เป็นหลัก

48a096debb2aa940.png

  1. โหลดแอปภายใต้เงื่อนไขเครือข่ายที่แตกต่างกันโดยใช้การควบคุมปริมาณจำลอง คุณจะใช้ Slow 3G เพื่อวัดเวลาในการโหลดใน Codelab นี้ เนื่องจากเป็นที่ที่ขนาดบันเดิลที่เล็กกว่าจะช่วยได้มากที่สุด

4397cb2c1327089.png

ตอนนี้ให้กระโดดและเริ่มย้ายแอปไปยัง API แบบโมดูลาร์ใหม่

4. ใช้แพ็คเกจความเข้ากันได้

แพ็คเกจความเข้ากันได้ช่วยให้คุณสามารถอัปเกรดเป็น SDK เวอร์ชันใหม่ได้โดยไม่ต้องเปลี่ยนโค้ด Firebase ทั้งหมดในคราวเดียว คุณสามารถอัปเกรดเป็นโมดูลาร์ API ได้ทีละน้อย

ในขั้นตอนนี้ คุณจะอัปเกรดไลบรารี Firebase จาก v8 เป็นเวอร์ชันใหม่และเปลี่ยนโค้ดเพื่อใช้แพ็คเกจความเข้ากันได้ ในขั้นตอนต่อไปนี้ คุณจะได้เรียนรู้วิธีอัปเกรดเฉพาะโค้ด Firebase Auth เพื่อใช้ Modular API ก่อน จากนั้นจึงอัปเกรดโค้ด Firestore

เมื่อสิ้นสุดแต่ละขั้นตอน คุณควรจะสามารถคอมไพล์และรันแอปได้โดยไม่เกิดความเสียหาย และเห็นขนาดมัดที่ลดลงเมื่อเราย้ายแต่ละผลิตภัณฑ์

รับ SDK ใหม่

ค้นหาส่วนการขึ้นต่อกันใน package.json และแทนที่ด้วยส่วนต่อไปนี้:

แพ็คเกจ.json

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

ติดตั้งการอ้างอิงอีกครั้ง

เนื่องจากเราเปลี่ยนเวอร์ชันของการขึ้นต่อกัน เราจำเป็นต้องรัน npm install อีกครั้งเพื่อรับการขึ้นต่อกันเวอร์ชันใหม่

เปลี่ยนเส้นทางการนำเข้า

แพ็คเกจความเข้ากันได้จะถูกเปิดเผยภายใต้ submodule 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. เล่นกับแอพ ทุกอย่างควรจะยังคงทำงานอยู่

5. อัปเกรด Auth เพื่อใช้ Modular API

คุณจะอัปเกรดผลิตภัณฑ์ Firebase ตามลำดับใดก็ได้ ใน Codelab นี้ คุณจะต้องอัปเกรด Auth ก่อนเพื่อเรียนรู้แนวคิดพื้นฐานเนื่องจาก Auth API นั้นค่อนข้างง่าย การอัปเกรด Firestore มีส่วนเกี่ยวข้องมากกว่าเล็กน้อย และคุณจะได้เรียนรู้วิธีดำเนินการดังกล่าวต่อไป

อัปเดตการเริ่มต้นการตรวจสอบสิทธิ์

  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 ออกจาก import { firebaseAuth, User } from './firebase'; เนื่องจากคุณได้นำเข้า User จาก 'firebase/auth'. แล้ว
  2. อัปเดตฟังก์ชันเพื่อใช้ API แบบโมดูลาร์

ดังที่คุณได้เห็นแล้วก่อนหน้านี้เมื่อเราอัปเดตคำสั่งการนำเข้า แพ็คเกจในเวอร์ชัน 9 ได้รับการจัดระเบียบตามฟังก์ชันที่คุณสามารถนำเข้าได้ ตรงกันข้ามกับ API เวอร์ชัน 8 ซึ่งอิงตามเนมสเปซแบบ dot-chained และรูปแบบบริการ การจัดระเบียบโค้ดแบบใหม่นี้ทำให้สามารถเขย่าโค้ดที่ไม่ได้ใช้ได้ เนื่องจากช่วยให้เครื่องมือสร้างสามารถวิเคราะห์โค้ดที่ใช้และโค้ดที่ไม่ได้ใช้

ในเวอร์ชัน 9 บริการจะถูกส่งผ่านเป็นอาร์กิวเมนต์แรกไปยังฟังก์ชัน Services คือออบเจ็กต์ที่คุณได้รับจากการเริ่มต้นบริการ 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. เปิด Chrome DevTools
  2. สลับไปที่แท็บ เครือข่าย
  3. รีเฟรชเพจเพื่อบันทึกคำขอเครือข่าย
  4. มองหา main.js และตรวจสอบขนาดของมัน คุณได้ลดขนาดบันเดิลลง 100KB (36 KB gzipped) หรือเล็กลงประมาณ 22% โดยการเปลี่ยนโค้ดเพียงไม่กี่บรรทัด! ไซต์ยังโหลดเร็วขึ้น 0.75 วินาทีด้วยการเชื่อมต่อ 3g ที่ช้า

2e4eafaf66cd829b.png

6. อัปเกรดแอป Firebase และ Firestore เพื่อใช้ Modular API

อัปเดตการเริ่มต้น Firebase

  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.appspot.com", 
    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() สำหรับการใช้งานที่สมบูรณ์

อัปเดตการสมัครสมาชิกToAllTickerChanges()

ขั้นแรก คุณจะต้องใช้ 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. เปิด Chrome DevTools
  2. สลับไปที่แท็บ เครือข่าย
  3. รีเฟรชเพจเพื่อบันทึกคำขอเครือข่าย
  4. มองหา main.js และตรวจสอบขนาดของมัน เปรียบเทียบกับขนาดบันเดิลเดิมอีกครั้ง - เราได้ลดขนาดบันเดิลลงกว่า 200KB (63.8 KB gzipped) หรือเล็กลง 50% ซึ่งแปลว่าโหลดเร็วขึ้น 1.3 วินาที!

7660cdc574ee8571.png

7. ใช้ Firestore Lite เพื่อเพิ่มความเร็วในการเรนเดอร์หน้าแรก

Firestore Lite คืออะไร?

Firestore SDK นำเสนอแคชที่ซับซ้อน การสตรีมแบบเรียลไทม์ พื้นที่จัดเก็บถาวร การซิงค์ออฟไลน์แบบหลายแท็บ การลองใหม่ การทำงานพร้อมกันในแง่ดี และอื่นๆ อีกมากมาย ดังนั้นจึงมีขนาดค่อนข้างใหญ่ แต่คุณอาจต้องการรับข้อมูลเพียงครั้งเดียว โดยไม่ต้องใช้ฟีเจอร์ขั้นสูงใดๆ ในกรณีเหล่านั้น Firestore ได้สร้างโซลูชันที่เรียบง่ายและเบา ซึ่งเป็นแพ็คเกจใหม่ล่าสุด — Firestore Lite

กรณีการใช้งานที่ยอดเยี่ยมอย่างหนึ่งสำหรับ Firestore Lite คือการเพิ่มประสิทธิภาพการแสดงผลหน้าแรก โดยคุณเพียงแค่ต้องรู้ว่าผู้ใช้เข้าสู่ระบบหรือไม่ จากนั้นจึงอ่านข้อมูลบางส่วนจาก Firetore เพื่อแสดง

ในขั้นตอนนี้ คุณจะได้เรียนรู้วิธีใช้ Firestore lite เพื่อลดขนาดบันเดิลเพื่อเพิ่มความเร็วในการเรนเดอร์หน้าแรก จากนั้นโหลด Firestore SDK หลักแบบไดนามิกเพื่อสมัครรับการอัปเดตแบบเรียลไทม์

คุณจะปรับโครงสร้างโค้ดใหม่เป็น:

  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 block ที่ป้องกันไว้ ฟังก์ชันการทำงานจะถูกย้ายไปยังฟังก์ชันใหม่ที่คุณจะสร้างขึ้นในขั้นตอนถัดไป

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. คุณจะต้องมีฟังก์ชันที่สร้างขึ้นใหม่เพื่อดึงข้อมูลสำหรับการแสดงผลหน้าแรก และฟังก์ชันตัวช่วยสองสามตัวเพื่อจัดการสถานะแอป ตอนนี้อัปเดตการนำเข้า:

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 โดยใช้การนำเข้าแบบไดนามิกที่ด้านบนของไฟล์ Variable loadRealtimeService คือคำมั่นสัญญาที่จะแก้ไขด้วยบริการแบบเรียลไทม์เมื่อโหลดโค้ดแล้ว คุณจะใช้ในภายหลังเพื่อสมัครรับการอัปเดตแบบเรียลไทม์

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. เปิด Chrome Devtools
  2. สลับไปที่แท็บ เครือข่าย
  3. รีเฟรชเพจเพื่อบันทึกคำขอเครือข่าย
  4. มองหา main.js และตรวจสอบขนาดของมัน
  5. ตอนนี้มีขนาดเพียง 115KB (34.5KB gzipped) ซึ่งมีขนาดเล็กกว่าขนาดบันเดิลเดิมถึง 75% ซึ่งก็คือ 446KB(138KB gzipped)! ด้วยเหตุนี้ ไซต์จึงโหลดเร็วขึ้นกว่า 2 วินาทีบนการเชื่อมต่อ 3G ซึ่งเป็นการปรับปรุงประสิทธิภาพและประสบการณ์ผู้ใช้ที่ยอดเยี่ยม!

9ea7398a8c8ef81b.png

8. ขอแสดงความยินดี

ยินดีด้วย คุณอัปเกรดแอปสำเร็จแล้วและทำให้มันเล็กลงและเร็วขึ้น!

คุณใช้แพ็คเกจที่เข้ากันได้เพื่ออัปเกรดแอปทีละชิ้น และใช้ Firestore Lite เพื่อเพิ่มความเร็วในการเรนเดอร์หน้าแรก จากนั้นโหลด Firestore หลักแบบไดนามิกเพื่อสตรีมการเปลี่ยนแปลงราคา

คุณยังลดขนาดบันเดิลและปรับปรุงเวลาในการโหลดตลอดหลักสูตร Codelab นี้ด้วย:

main.js

ขนาดทรัพยากร (kb)

ขนาดไฟล์ gzip (kb)

เวลาในการโหลด (มากกว่า 3g ช้า)

v8

446

138

4.92

รองรับ v9

429

124

4.65

v9 การรับรองความถูกต้องแบบโมดูลาร์เท่านั้น

348

102

4.2

v9 แบบโมดูลาร์เต็มรูปแบบ

244

74.6

3.66

v9 แบบแยกส่วนอย่างสมบูรณ์ + Firestore lite

117

34.9

2.88

32a71bd5a774e035.png

ตอนนี้คุณรู้ขั้นตอนสำคัญที่จำเป็นในการอัปเกรดเว็บแอปที่ใช้ v8 Firebase JS SDK เพื่อใช้ JS SDK แบบโมดูลาร์ใหม่

อ่านเพิ่มเติม

เอกสารอ้างอิง