1. ก่อนเริ่มต้น
Firebase JS SDK แบบโมดูลเป็นการเขียน JS SDK ที่มีอยู่ใหม่และจะเปิดตัวเป็นเวอร์ชันหลักเวอร์ชันถัดไป ซึ่งช่วยให้นักพัฒนาแอปยกเว้นโค้ดที่ไม่ได้ใช้จาก Firebase JS SDK เพื่อสร้างแพ็กเกจขนาดเล็กลงและมีประสิทธิภาพดีขึ้น
ความแตกต่างที่เห็นได้ชัดที่สุดของ JS SDK แบบโมดูลคือตอนนี้ฟีเจอร์ต่างๆ จะจัดระเบียบไว้ในฟังก์ชันแบบลอยอิสระที่คุณจะนําเข้า แทนที่จะอยู่ในเนมสเปซ firebase
เดียวที่มีทุกอย่าง วิธีใหม่ในการจัดระเบียบโค้ดนี้ช่วยให้สามารถแยกไฟล์ที่ไม่จำเป็นออกได้ และคุณจะได้เรียนรู้วิธีอัปเกรดแอปที่ใช้ Firebase JS SDK เวอร์ชัน 8 อยู่ให้เป็นเวอร์ชันใหม่แบบโมดูล
เรามีชุดแพ็กเกจความเข้ากันได้เพื่อให้กระบวนการอัปเกรดเป็นไปอย่างราบรื่น ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีใช้แพ็กเกจความเข้ากันได้เพื่อพอร์ตแอปทีละส่วน
สิ่งที่คุณจะสร้าง
ในโค้ดแล็บนี้ คุณจะค่อยๆ ย้ายข้อมูลเว็บแอปรายการติดตามหุ้นที่มีอยู่ซึ่งใช้ JS SDK เวอร์ชัน 8 ไปยัง JS SDK แบบโมดูลใหม่ใน 3 ระยะ ดังนี้
- อัปเกรดแอปเพื่อใช้แพ็กเกจความเข้ากันได้
- อัปเกรดแอปจากแพ็กเกจความเข้ากันได้เป็น API แบบโมดูลทีละส่วน
- ใช้ Firestore Lite ซึ่งเป็นการติดตั้งใช้งาน Firestore SDK แบบเบาเพื่อปรับปรุงประสิทธิภาพของแอปให้ดียิ่งขึ้น
โค้ดแล็บนี้มุ่งเน้นที่การอัปเกรด Firebase SDK แนวคิดและบล็อกโค้ดอื่นๆ ไม่ได้อธิบายอย่างละเอียด แต่มีไว้เพื่อให้คุณคัดลอกและวางได้ง่ายๆ
สิ่งที่ต้องมี
2. ตั้งค่า
รับรหัส
ทุกอย่างที่คุณต้องการสำหรับโปรเจ็กต์นี้อยู่ในที่เก็บ Git ในการเริ่มต้นใช้งาน คุณจะต้องคัดลอกโค้ดและเปิดในสภาพแวดล้อมการพัฒนาที่ชื่นชอบ
โคลนที่เก็บ GitHub ของโค้ดแล็บจากบรรทัดคำสั่งโดยทำดังนี้
git clone https://github.com/FirebaseExtended/codelab-modular-sdk.git
หรือหากไม่ได้ติดตั้ง git ไว้ คุณสามารถดาวน์โหลดที่เก็บเป็นไฟล์ ZIP และแตกไฟล์ ZIP ที่ดาวน์โหลด
นําเข้าแอป
- ใช้ IDE เพื่อเปิดหรือนําเข้าไดเรกทอรี
codelab-modular-sdk
- เรียกใช้
npm install
เพื่อติดตั้งไลบรารีที่จำเป็นต่อการสร้างและเรียกใช้แอปในเครื่อง - เรียกใช้
npm run build
เพื่อสร้างแอป - เรียกใช้
npm run serve
เพื่อเริ่มเว็บเซิร์ฟเวอร์ - เปิดแท็บเบราว์เซอร์ไปที่ http://localhost:8080
3. กำหนดพื้นฐาน
จุดเริ่มต้นของคุณคืออะไร
จุดเริ่มต้นของคุณคือแอปรายการติดตามหุ้นที่ออกแบบมาสำหรับ Codelab นี้ โค้ดนี้เรียบง่ายขึ้นเพื่อแสดงแนวคิดในโค้ดแล็บนี้ และมีการแก้ไขข้อผิดพลาดเพียงเล็กน้อย หากเลือกที่จะนำโค้ดนี้มาใช้ซ้ำในแอปเวอร์ชันที่ใช้งานจริง โปรดตรวจสอบว่าคุณจัดการข้อผิดพลาดและทดสอบโค้ดทั้งหมดอย่างสมบูรณ์แล้ว
ตรวจสอบว่าทุกอย่างในแอปใช้งานได้ โดยทำดังนี้
- เข้าสู่ระบบแบบไม่ระบุตัวตนโดยใช้ปุ่มเข้าสู่ระบบที่มุมขวาบน
- หลังจากเข้าสู่ระบบแล้ว ให้ค้นหาและเพิ่ม "NFLX", "SBUX" และ "T" ลงในรายการติดตามโดยคลิกปุ่มเพิ่ม พิมพ์ตัวอักษร และคลิกแถวผลการค้นหาที่ปรากฏขึ้นด้านล่าง
- นำหุ้นออกจากรายการติดตามโดยคลิก x ที่ท้ายแถว
- ดูการอัปเดตราคาหุ้นแบบเรียลไทม์
- เปิดเครื่องมือสําหรับนักพัฒนาเว็บใน Chrome ไปที่แท็บ Network แล้วเลือกปิดใช้แคชและใช้แถวคําขอขนาดใหญ่ ปิดใช้แคชช่วยให้เราได้รับการเปลี่ยนแปลงล่าสุดเสมอหลังจากการรีเฟรช และใช้แถวคำขอขนาดใหญ่จะทำให้แถวแสดงทั้งขนาดที่ส่งและขนาดทรัพยากรของทรัพยากร ใน Codelab นี้ เราสนใจขนาดของ
main.js
เป็นหลัก
- โหลดแอปภายใต้เงื่อนไขเครือข่ายที่ต่างกันโดยใช้การควบคุมแบบจําลอง คุณจะใช้ 3G ที่ช้าเพื่อวัดเวลาในการโหลดในโค้ดแล็บนี้ เนื่องจากเป็นเครือข่ายที่ขนาด Bundle ที่เล็กลงจะมีประโยชน์มากที่สุด
ตอนนี้ก็เริ่มย้ายข้อมูลแอปไปยัง API แบบโมดูลใหม่ได้เลย
4. ใช้แพ็กเกจความเข้ากันได้
แพ็กเกจความเข้ากันได้ช่วยให้คุณอัปเกรดเป็น SDK เวอร์ชันใหม่ได้โดยไม่ต้องเปลี่ยนโค้ด Firebase ทั้งหมดพร้อมกัน คุณสามารถอัปเกรดเป็น API แบบโมดูลทีละน้อยได้
ในขั้นตอนนี้ คุณจะอัปเกรดไลบรารี Firebase จาก v8 เป็นเวอร์ชันใหม่และเปลี่ยนโค้ดให้ใช้แพ็กเกจความเข้ากันได้ ในขั้นตอนต่อไปนี้ คุณจะได้เรียนรู้วิธีอัปเกรดเฉพาะโค้ด Firebase Auth เพื่อใช้ API แบบโมดูลก่อน จากนั้นจึงอัปเกรดโค้ด Firestore
เมื่อสิ้นสุดแต่ละขั้นตอน คุณควรจะคอมไพล์และเรียกใช้แอปได้โดยไม่มีปัญหา และเห็นขนาด App Bundle ลดลงเมื่อเราย้ายข้อมูลผลิตภัณฑ์แต่ละรายการ
รับ SDK ใหม่
ค้นหาส่วน Dependency ใน package.json
แล้วแทนที่ด้วยข้อมูลต่อไปนี้
package.json
"dependencies": {
"firebase": "^9.0.0"
}
ติดตั้งการอ้างอิงอีกครั้ง
เนื่องจากเราเปลี่ยนเวอร์ชันของข้อกำหนด เราจึงต้องเรียกใช้ npm install
อีกครั้งเพื่อรับข้อกำหนดเวอร์ชันใหม่
เปลี่ยนเส้นทางการนําเข้า
แพ็กเกจความเข้ากันได้จะแสดงอยู่ในโมดูลย่อย firebase/compat
ดังนั้นเราจะอัปเดตเส้นทางการนําเข้าให้สอดคล้องกับข้อมูลต่อไปนี้
- ไปที่ไฟล์
src/firebase.ts
- แทนที่การนําเข้าที่มีอยู่ด้วยการนําเข้าต่อไปนี้
src/firebase.ts
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
ยืนยันว่าแอปใช้งานได้
- เรียกใช้
npm run build
เพื่อสร้างแอปอีกครั้ง - เปิดแท็บเบราว์เซอร์ไปที่ http://localhost:8080 หรือรีเฟรชแท็บที่มีอยู่
- ลองใช้แอปดู ทุกอย่างควรจะยังทำงานอยู่
5. อัปเกรด Auth เพื่อใช้ API แบบโมดูล
คุณอัปเกรดผลิตภัณฑ์ Firebase ได้ทุกลำดับ ในโค้ดแล็บนี้ คุณจะอัปเกรด Auth ก่อนเพื่อเรียนรู้แนวคิดพื้นฐาน เนื่องจาก Auth API ค่อนข้างง่าย การอัปเกรด Firestore นั้นซับซ้อนกว่าเล็กน้อย และคุณจะได้ดูวิธีดำเนินการในลำดับถัดไป
อัปเดตการเริ่มต้นการตรวจสอบสิทธิ์
- ไปที่ไฟล์
src/firebase.ts
- เพิ่มการนําเข้าต่อไปนี้
src/firebase.ts
import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
- ลบ
import ‘firebase/compat/auth'.
- แทนที่
export const firebaseAuth = app.auth();
ด้วย
src/firebase.ts
export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
- นำ
export type User = firebase.User;
ที่ท้ายไฟล์ออก ระบบจะส่งออกUser
โดยตรงในsrc/auth.ts
ซึ่งคุณจะเปลี่ยนในลำดับถัดไป
อัปเดตรหัสการตรวจสอบสิทธิ์
- ไปที่ไฟล์
src/auth.ts
- เพิ่มการนําเข้าต่อไปนี้ที่ด้านบนของไฟล์
src/auth.ts
import {
signInAnonymously,
signOut,
onAuthStateChanged,
User
} from 'firebase/auth';
- นำ
User
ออกจากimport { firebaseAuth, User } from './firebase';
เนื่องจากคุณได้นำเข้าUser
จาก‘firebase/auth'.
แล้ว - อัปเดตฟังก์ชันเพื่อใช้ API แบบโมดูล
ดังที่คุณได้เห็นก่อนหน้านี้เมื่อเราอัปเดตคำสั่งการนําเข้า แพ็กเกจในเวอร์ชัน 9 จะจัดระเบียบตามฟังก์ชันที่คุณนําเข้าได้ ซึ่งแตกต่างจาก API เวอร์ชัน 8 ที่ใช้รูปแบบบริการและเนมสเปซแบบเชนจุด การจัดระเบียบโค้ดใหม่นี้ช่วยให้สามารถแยกโค้ดที่ไม่ได้ใช้ออกได้ เนื่องจากช่วยให้เครื่องมือสร้างวิเคราะห์ได้ว่าโค้ดใดมีการใช้งานและโค้ดใดไม่มีการใช้งาน
ในเวอร์ชัน 9 ระบบจะส่งบริการเป็นอาร์กิวเมนต์แรกไปยังฟังก์ชัน บริการคือออบเจ็กต์ที่คุณได้รับจากการเริ่มต้นบริการ 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';
ยืนยันว่าแอปใช้งานได้
- เรียกใช้
npm run build
เพื่อสร้างแอปอีกครั้ง - เปิดแท็บเบราว์เซอร์ไปที่ http://localhost:8080 หรือรีเฟรชแท็บที่มีอยู่
- ลองใช้แอปดู ทุกอย่างควรจะยังทำงานอยู่
ตรวจสอบขนาดกลุ่ม
- เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
- เปลี่ยนไปใช้แท็บเครือข่าย
- รีเฟรชหน้าเว็บเพื่อบันทึกคําขอเครือข่าย
- มองหา main.js และตรวจสอบขนาด คุณได้ลดขนาดแพ็กเกจลง 100 KB (36 KB เมื่อใช้การบีบอัดข้อมูลด้วย GZIP) หรือเล็กลงประมาณ 22% โดยการเปลี่ยนโค้ดเพียงไม่กี่บรรทัด นอกจากนี้ เว็บไซต์ยังโหลดเร็วขึ้น 0.75 วินาทีในการเชื่อมต่อ 3G ที่ช้า
6. อัปเกรดแอป Firebase และ Firestore เพื่อใช้ API แบบโมดูล
อัปเดตการเริ่มต้นใช้งาน Firebase
- ไปที่ไฟล์
src/firebase.ts.
- แทนที่
import firebase from ‘firebase/compat/app';
ด้วย
src/firebase.ts
import { initializeApp } from 'firebase/app';
- แทนที่
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
- ในไฟล์เดียวกัน
src/firebase.ts,
ให้แทนที่import 'firebase/compat/firestore';
ด้วย
src/firebase.ts
import { getFirestore } from 'firebase/firestore';
- แทนที่
export const firestore = app.firestore();
ด้วย
src/firebase.ts
export const firestore = getFirestore();
- นำบรรทัดทั้งหมดหลัง "
export const firestore = ...
" ออก
อัปเดตการนําเข้า
- เปิดไฟล์
src/services.ts.
- นำ
FirestoreFieldPath
,FirestoreFieldValue
และQuerySnapshot
ออกจากการนําเข้า ตอนนี้การนําเข้าจาก'./firebase'
ควรมีลักษณะดังต่อไปนี้
src/services.ts
import { firestore } from './firebase';
- นําเข้าฟังก์ชันและประเภทที่คุณจะใช้ในด้านบนของไฟล์
**src/services.ts**
import {
collection,
getDocs,
doc,
setDoc,
arrayUnion,
arrayRemove,
onSnapshot,
query,
where,
documentId,
QuerySnapshot
} from 'firebase/firestore';
อัปเดต search()
- สร้างการอ้างอิงถึงคอลเล็กชันที่มีทิกเกอร์ทั้งหมด
src/services.ts
const tickersCollRef = collection(firestore, 'current');
- ใช้
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()
ในทำนองเดียวกัน ให้นำข้อมูล Ticker ออกจากรายการที่อยากดูของผู้ใช้โดยใช้ 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()
- ใช้
doc()
เพื่อสร้างการอ้างอิงเอกสารไปยังรายการติดตามของผู้ใช้ก่อน จากนั้นฟังการเปลี่ยนแปลงรายการติดตามโดยใช้onSnapshot()
src/services.ts
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
/* subscribe to ticker price changes */
});
- เมื่อเพิ่มข้อมูล Ticker ไว้ในรายการติดตามแล้ว ให้ใช้
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);
});
}
ยืนยันว่าแอปใช้งานได้
- เรียกใช้
npm run build
เพื่อสร้างแอปอีกครั้ง - เปิดแท็บเบราว์เซอร์ไปที่ http://localhost:8080 หรือรีเฟรชแท็บที่มีอยู่
- ลองใช้แอปดู ทุกอย่างควรจะยังทำงานอยู่
ตรวจสอบขนาดกลุ่ม
- เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
- เปลี่ยนไปใช้แท็บเครือข่าย
- รีเฟรชหน้าเว็บเพื่อบันทึกคําขอเครือข่าย
- มองหา
main.js
และตรวจสอบขนาด เมื่อเปรียบเทียบกับขนาด App Bundle เดิม เราลดขนาด App Bundle ลงได้กว่า 200 KB (63.8 KB เมื่อใช้การบีบอัดข้อมูลด้วย GZIP) หรือเล็กลง 50% ซึ่งทำให้เวลาในการโหลดเร็วขึ้น 1.3 วินาที
7. ใช้ Firestore Lite เพื่อเพิ่มความเร็วในการแสดงผลหน้าเว็บครั้งแรก
Firestore Lite คืออะไร
Firestore SDK มีแคชที่ซับซ้อน สตรีมมิงแบบเรียลไทม์ พื้นที่เก็บข้อมูลถาวร การซิงค์แบบออฟไลน์หลายแท็บ การลองอีกครั้ง การทํางานพร้อมกันแบบมองโลกในแง่ดี และอื่นๆ อีกมากมาย จึงมีขนาดใหญ่ แต่คุณอาจต้องการรับข้อมูลเพียงครั้งเดียวโดยไม่จำเป็นต้องใช้ฟีเจอร์ขั้นสูงใดๆ สำหรับกรณีดังกล่าว Firestore ได้สร้างโซลูชันที่เรียบง่ายและเบาแพ็กเกจใหม่อย่าง Firestore Lite
Use Case ที่ยอดเยี่ยมอย่างหนึ่งของ Firestore Lite คือการเพิ่มประสิทธิภาพการแสดงผลหน้าเว็บครั้งแรก โดยคุณเพียงต้องทราบว่าผู้ใช้เข้าสู่ระบบอยู่หรือไม่ จากนั้นอ่านข้อมูลบางอย่างจาก Firestore เพื่อแสดง
ในขั้นตอนนี้ คุณจะได้เรียนรู้วิธีใช้ Firestore Lite เพื่อลดขนาด Bundle เพื่อเร่งการแสดงผลหน้าเว็บครั้งแรก จากนั้นโหลด Firestore SDK หลักแบบไดนามิกเพื่อสมัครรับการอัปเดตแบบเรียลไทม์
คุณจะเปลี่ยนรูปแบบโค้ดเพื่อดำเนินการต่อไปนี้
- ย้ายบริการแบบเรียลไทม์ไปยังไฟล์แยกต่างหากเพื่อให้โหลดแบบไดนามิกได้โดยใช้การนําเข้าแบบไดนามิก
- สร้างฟังก์ชันใหม่เพื่อใช้ Firestore Lite เพื่อดึงข้อมูลรายการติดตามและราคาหุ้น
- ใช้ฟังก์ชัน Firestore Lite ใหม่เพื่อดึงข้อมูลเพื่อทำการแสดงผลหน้าเว็บครั้งแรก จากนั้นโหลดบริการแบบเรียลไทม์แบบไดนามิกเพื่อรับการอัปเดตแบบเรียลไทม์
ย้ายบริการแบบเรียลไทม์ไปยังไฟล์ใหม่
- สร้างไฟล์ใหม่ชื่อ
src/services.realtime.ts.
- ย้ายฟังก์ชัน
subscribeToTickerChanges()
และsubscribeToAllTickerChanges()
จากsrc/services.ts
ไปยังไฟล์ใหม่ - เพิ่มการนําเข้าที่จําเป็นไว้ที่ด้านบนของไฟล์ใหม่
คุณยังต้องทําการเปลี่ยนแปลงอีก 2-3 อย่างที่นี่
- ก่อนอื่น ให้สร้างอินสแตนซ์ Firestore จาก Firestore SDK หลักที่ด้านบนของไฟล์เพื่อใช้ในฟังก์ชัน คุณไม่สามารถนําเข้าอินสแตนซ์ Firestore จาก
firebase.ts
ที่นี่ได้ เนื่องจากคุณจะเปลี่ยนเป็นอินสแตนซ์ Firestore Lite ในอีก 2-3 ขั้นตอน ซึ่งจะใช้สําหรับการแสดงผลหน้าเว็บครั้งแรกเท่านั้น - ประการที่ 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 เพื่อดึงข้อมูล
- เปิด
src/services.ts.
- เปลี่ยนเส้นทางการนําเข้าจาก
‘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';
- เพิ่มฟังก์ชันเพื่อดึงข้อมูลที่จำเป็นสำหรับการแสดงผลหน้าเว็บครั้งแรกโดยใช้ 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);
}
- เปิด
src/firebase.ts
แล้วเปลี่ยนเส้นทางการนําเข้าจาก‘firebase/firestore'
เป็น‘firebase/firestore/lite':
src/firebase.ts
import { getFirestore } from 'firebase/firestore/lite';
รวมทั้งหมดเข้าด้วยกัน
- เปิด
src/main.ts.
- คุณจะต้องมีฟังก์ชันที่สร้างขึ้นใหม่เพื่อดึงข้อมูลสำหรับการแสดงผลหน้าเว็บครั้งแรก และฟังก์ชันตัวช่วย 2-3 รายการเพื่อจัดการสถานะแอป ดังนั้นให้อัปเดตการนําเข้าดังนี้
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';
- โหลด
src/services.realtime
โดยใช้การนําเข้าแบบไดนามิกที่ด้านบนของไฟล์ ตัวแปรloadRealtimeService
คือสัญญาว่าจะแก้ปัญหาด้วยบริการแบบเรียลไทม์เมื่อโหลดโค้ด คุณจะใช้รหัสนี้ในภายหลังเพื่อสมัครรับข้อมูลอัปเดตแบบเรียลไทม์
src/main.ts
const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
setRealtimeServicesLoaded(true);
});
- เปลี่ยนการเรียกกลับของ
onUserChange()
เป็นฟังก์ชันasync
เพื่อให้เราใช้await
ในเนื้อหาของฟังก์ชันได้
src/main.ts
onUserChange(async user => {
// callback body
});
- ตอนนี้ให้ดึงข้อมูลเพื่อทำให้หน้าเว็บแสดงผลครั้งแรกโดยใช้ฟังก์ชันใหม่ที่สร้างขึ้นในขั้นตอนก่อนหน้า
ใน onUserChange()
callback ให้ค้นหาเงื่อนไข 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
}
}
- ในบล็อก 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
ตรวจสอบว่าแอปทำงานได้
- เรียกใช้
npm run build
เพื่อสร้างแอปอีกครั้ง - เปิดแท็บเบราว์เซอร์ไปที่ http://localhost:8080 หรือรีเฟรชแท็บที่มีอยู่
ตรวจสอบขนาดกลุ่ม
- เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
- เปลี่ยนไปใช้แท็บเครือข่าย
- รีเฟรชหน้าเว็บเพื่อบันทึกคําขอเครือข่าย
- มองหา
main.js
แล้วตรวจสอบขนาด - ตอนนี้เหลือเพียง 115 KB (34.5 KB เมื่อใช้การบีบอัดไฟล์ GZIP) ซึ่งเล็กกว่าขนาดเดิมของกลุ่มที่ 446 KB(138 KB เมื่อใช้การบีบอัด GZIP) 75% ด้วยเหตุนี้ เว็บไซต์จึงโหลดเร็วขึ้นกว่า 2 วินาทีในการเชื่อมต่อ 3G ซึ่งเป็นการปรับปรุงประสิทธิภาพและประสบการณ์ของผู้ใช้ที่ยอดเยี่ยม
8. ขอแสดงความยินดี
ขอแสดงความยินดี คุณได้อัปเกรดแอปให้เล็กลงและเร็วขึ้นเรียบร้อยแล้ว
คุณใช้แพ็กเกจ compat เพื่ออัปเกรดแอปทีละส่วน และใช้ Firestore Lite เพื่อเร่งการแสดงผลหน้าเว็บครั้งแรก จากนั้นโหลด Firestore หลักแบบไดนามิกเพื่อสตรีมการเปลี่ยนแปลงราคา
นอกจากนี้ คุณยังลดขนาดของ Bundle และปรับปรุงเวลาในการโหลดตลอดระยะเวลาของ Codelab นี้ด้วย
main.js | ขนาดทรัพยากร (KB) | ขนาดไฟล์ที่บีบอัด (KB) | เวลาที่ใช้ในการโหลด (วินาที) (ผ่าน 3G ที่ช้า) |
v8 | 446 | 138 | 4.92 |
v9 compat | 429 | 124 | 4.65 |
การตรวจสอบสิทธิ์แบบโมดูลของ v9 เท่านั้น | 348 | 102 | 4.2 |
v9 แบบโมดูลทั้งหมด | 244 | 74.6 | 3.66 |
v9 แบบโมดูลทั้งหมด + Firestore Lite | 117 | 34.9 | 2.88 |
ตอนนี้คุณทราบขั้นตอนสําคัญที่จําเป็นในการอัปเกรดเว็บแอปที่ใช้ Firebase JS SDK เวอร์ชัน 8 เพื่อใช้ JS SDK แบบโมดูลใหม่แล้ว