用新的Firebase v9.x Web SDK重構一個React應用
Firebase Web SDK第9版的釋出,在管理使用者和查詢資料庫的方法上有了突破性的變化。在Firebase v8.x中編寫的程式碼在v9.x中使用時將會出現錯誤,這就需要進行重構。
在這篇文章中,我們將學習如何重構一個使用Firebase Web SDK v8.x到v9.x的React應用程式,這也被稱為模組化的Web SDK。對於我們的例子,我們將使用一個用v8.x構建的亞馬遜克隆,並將其重構到v9.x。
前提條件
要跟上這個教程,你應該熟悉React和Firebase v8.x,你還應該在你的機器上安裝Node.js。
介紹Firebase v9.x Web SDK
新的Web SDK擺脫了第8版中使用的名稱空間方法。取而代之的是,它採用了一種優化的模組化格式,以消除不使用的程式碼,例如,樹形搖動,從而大大減少了JavaScript捆綁的大小。
向模組化方法的過渡引入了一些破壞性的變化,使得新的庫向後不相容,並導致v8.x中使用的程式碼在新的Firebase v9.x SDK中出現錯誤。
下面的程式碼顯示了新庫中引入的一些破壞性變化。
``` // VERSION 8 import firebase from 'firebase/app'; import 'firebase/auth';
firebase.initializeApp(); const auth = firebase.auth();
auth.onAuthStateChanged(user => { // Check for user status });
// VERSION 9 EQUIVALENT import { initializeApp } from 'firebase/app'; import { getAuth, onAuthStateChanged } from 'firebase/auth';
const firebaseApp = initializeApp(); const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => { // Check for user status });
```
上面的兩個程式碼樣本都監控了一個使用者狀態。雖然兩者使用的程式碼行數相似,但在v9.x中,我們沒有匯入firebase
名稱空間或firebase/auth
副作用,該副作用將認證服務增強到firebase
名稱空間中,而是匯入並使用單個函式。
這些變化利用了現代JavaScript工具如Webpack和Rollup的程式碼消除功能。
例如,上面的v8.x程式碼包括以下程式碼片斷。
``` auth.onAuthStateChanged(user => { // Check for user status });
```
auth
是一個名稱空間和一個服務,包含onAuthStateChanged
方法。該名稱空間還包含像signInWithEmailAndPassword
、createUserWithEmailAndPassword
、signOut
,這些方法沒有被程式碼使用。當我們捆綁整個程式碼時,這些未使用的方法也會被包含在捆綁中,從而導致相對大小的增加。
儘管像Webpack和Rollup這樣的捆綁器可以用來消除未使用的程式碼,但由於名稱空間的方法,它們將沒有任何效果。解決這個問題是重塑API表面的主要目標之一,以採取模組化的形式。要了解更多關於新庫變化背後的原因,請檢視Firebase官方部落格。
Firebase相容性庫
新的SDK還包括一個具有熟悉的API表面的相容庫,它與v8.x完全相容。相容庫允許我們在同一個程式碼庫中同時使用新舊API,使我們能夠逐步重構我們的應用而不破壞它。我們可以通過對匯入路徑做一些調整來使用相容庫,如下所示。
``` import firebase from 'firebase/compat/app'; import 'firebase/compat/auth'; import 'firebase/compat/firestore';
```
當我們重構我們的Amazon克隆應用時,我們將利用這個庫的優勢。
Firebase Web SDK v9.x的好處
簡而言之,Firebase Web SDK v9.x提供了縮小的尺寸和增加的整體效能。通過像Webpack和Rollup這樣的JavaScript工具來利用程式碼消除功能,新的Web SDK提供了更快的網路體驗。據Firebase官方Twitter賬戶稱,由於採用了新的模組化形狀,新的SDK據說比前代產品小了約80%。
設定我們的React應用進行重構
現在我們已經熟悉了新的SDK,讓我們來學習如何重構我們的v8.x應用。本節中我們將使用的亞馬遜克隆應用是一個使用Firebase和Strapi構建的電子商務應用。
在我們的應用中,我們使用Firebase來增加一些功能,比如用Firebase認證來管理使用者身份,用Cloud Firestore來儲存認證使用者購買的產品。我們使用Strapi來處理在應用程式上購買的產品的付款。最後,我們用Express.js建立了一個API,用Strapi客戶端的祕密來響應即將用Firebase雲功能購買產品的客戶。
你可以訪問該網站的部署版本,它看起來像下面的圖片。
請隨意玩玩這個應用,以便更好地理解我們在這篇文章中的工作內容。
設定亞馬遜的克隆應用
在我們開始編碼之前,首先,讓我們從GitHub上克隆repo並安裝必要的npm包。開啟你的終端,導航到你想儲存React應用程式的資料夾。新增以下命令。
``` $ git clone http://github.com/Tammibriggs/Amazon-clone-FirebaseV8.git $ cd Amazon-clone-FirebaseV8
```
現在我們已經成功克隆了 repo,在安裝包之前,我們需要將package.json
檔案中的Firebase版本改為v9.x。
在根目錄下,開啟package.json
檔案,用"firebase": "9.2.0"
替換依賴物件中的"firebase": "8.10.0"
。現在,讓我們通過在終端執行以下命令來安裝我們應用程式的依賴項。
``` $ npm install $ cd functions $ npm install
```
儘管我們已經設定並安裝了我們應用程式的所有依賴項,但如果我們嘗試用npm start
來執行應用程式,它就會出現錯誤。為了避免這種情況,我們需要修復我們的應用程式的破壞性變化,這一點我們很快就會做到。
React應用程式的結構
我們的應用程式的src
目錄的結構如下,但我們已經刪除了所有的樣式檔案,使其看起來更短。
``` src ┣ Checkout ┃ ┣ Checkout.js ┃ ┣ CheckoutProduct.js ┃ ┗ Subtotal.js ┣ Header ┃ ┗ Header.js ┣ Home ┃ ┣ Home.js ┃ ┗ Product.js ┣ Login ┃ ┗ Login.js ┣ Orders ┃ ┣ Order.js ┃ ┗ Orders.js ┣ Payment ┃ ┣ axios.js ┃ ┗ Payment.js ┣ App.js ┣ firebase.js ┣ index.js ┣ reducer.js ┣ reportWebVitals.js ┗ StateProvider.js
```
我們將只處理使用Firebase服務的檔案,firebase
、App.js
、Header.js
、Login.js
、Payment.js
和Orders.js
。
將亞馬遜的克隆檔案重構為一個模組化的方法
讓我們更新到v9.x的compat庫,幫助我們逐步遷移到模組化方法,直到我們不再需要compat庫。
升級過程遵循一個重複的模式;首先,它將單一服務(如身份驗證)的程式碼重構為模組化風格,然後刪除該服務的compat庫。
更新匯入到9.x版本的compat庫
前往src
目錄中的firebase.js
檔案,修改v8.x的匯入,使其看起來像以下程式碼。
``` import firebase from 'firebase/app'; import 'firebase/auth'; import 'firebase/firestore';
```
僅僅做了一些改動,我們就將應用程式更新到了v9.x compat。現在,我們可以用npm start
來啟動我們的應用程式,它不會出現任何錯誤。我們還應該在本地啟動Firebase函式,以公開從Strapi獲取客戶祕密的API。
在你的終端,改變到functions
目錄,執行以下命令來啟動該函式。
``` $ firebase emulators:start
```
重構認證程式碼
在Login.js
,App.js
, 和Header.js
, 我們使用了Firebase認證服務。首先,讓我們重構Login.js
檔案中的程式碼,在這裡我們建立了建立使用者的功能,並通過FirebasecreateUserWithEmailAndPassword
和signInWithEmailAndPassword
方法來簽署他們。當我們掃描Login.js
檔案的時候,我們會看到下面的v8.x程式碼。
``` // src/Login/Login.js const signIn = e => { ... // signIn an existing user with email and password auth .signInWithEmailAndPassword(email, password) .... }
const regiter = e => { ... // Create a new user with email and password using firebase auth .createUserWithEmailAndPassword(email, password) .... }
```
為了遵循模組化的方法,我們將從auth
模組中匯入signInWithEmailAndPassword
和createUserWithEmailAndPassword
方法,然後更新程式碼。重構後的版本將看起來像下面的程式碼。
``` // src/Login/Login.js import {signInWithEmailAndPassword, createUserWithEmailAndPassword} from 'firebase/auth'
... const signIn = e => { ... // signIn an existing user with email and password signInWithEmailAndPassword(auth, email, password) ... } const regiter = e => { ... // Create a new user with email and password using firebase createUserWithEmailAndPassword(auth, email, password) ... }
```
現在,讓我們重構一下App.js
和Header.js
檔案。在App.js
檔案中,我們使用onAuthStateChanged
方法來監控使用者登入狀態的變化。
``` // src/App.js useEffect(() => { auth.onAuthStateChanged(authUser => { ... }) }, [])
```
上述程式碼的模組化v9.x看起來像下面這段。
``` // src/App.js import {onAuthStateChanged} from 'firebase/auth'
... useEffect(() => { onAuthStateChanged(auth, authUser => { ... }) }, [])
```
在Header.js
檔案中,我們使用signOut
方法來簽出已認證的使用者。
``` // src/Header/Header.js const handleAuthentication = () => { ... auth.signOut() ... }
```
更新上面的程式碼,使其看起來像下面的程式碼段。
``` // src/Header/Header.js import {signOut} from 'firebase/auth' ... const handleAuthentication = () => { ... signOut(auth) ... }
```
現在我們已經完成了對所有認證程式碼的重構,現在是時候刪除compat庫以獲得我們的規模優勢了。在firebase.js
檔案中,用以下程式碼替換import 'firebase/compat/auth'
和const auth = firebaseApp.auth()
。
``` import {getAuth} from 'firebase/auth' ... const auth = getAuth(firebaseApp)
```
重構Cloud Firestore程式碼
重構Cloud Firestore程式碼的過程與我們剛才對認證程式碼所做的相似。我們將與Payment.js
和Orders.js
檔案一起工作。在Payment.js
,我們使用Firestore來儲存在網站上支付產品的使用者的資料。在Payment.js
,我們會發現下面的v8.x程式碼。
``` // src/Payment/Payment.js ... db .collection('users') .doc(user?.uid) .collection('orders') .doc(paymentIntent.id) .set({ basket: basket, amount: paymentIntent.amount, created: paymentIntent.created }) ...
```
為了重構程式碼,我們首先要匯入必要的函式,然後更新程式碼的其他部分。上面程式碼的v9.x看起來像下面這樣。
``` // src/Payment/Payment.js import {doc, setDoc} from 'firebase/firestore'
... const ref = doc(db, 'users', user?.uid, 'orders', paymentIntent.id) setDoc(ref, { basket: basket, amount: paymentIntent.amount, created: paymentIntent.created }) ...
```
在Orders.js
檔案中,我們使用onSnapshot
方法來獲得Firestore中的資料的實時更新。v9.x的程式碼看起來如下。
``` // src/Orders/Orders.js .... db .collection('users') .doc(user?.uid) .collection('orders') .orderBy('created', 'desc') .onSnapshot(snapshot => { setOrders(snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() }))) }) ...
```
v9.x的對應程式碼如下。
``` import {query, collection, onSnapshot, orderBy} from 'firebase/firestore'
... const orderedOrders = query(ref, orderBy('created', 'desc')) onSnapshot(orderedOrders, snapshot => { setOrders(snapshot.docs.map(doc => ({ id: doc.id, data: doc.data() }))) }) ...
```
現在我們已經完成了對所有Cloud Firestore程式碼的重構,讓我們刪除compat庫。在firebase.js
檔案中,用以下程式碼替換import 'firebase/compat/firestore'
和const db = firebaseApp.firestore()
。
``` import { getFirestore } from "firebase/firestore"; ... const db = getFirestore(firebaseApp) ...
```
更新初始化程式碼
將我們的亞馬遜克隆應用升級到新的模組化v9.x語法的最後一步是更新初始化程式碼。在firebase.js
檔案中,用以下函式替換import firebase from 'firebase/compat/app';
和 constfirebaseApp = firebase.initializeApp(firebaseConfig)
。
``` import { initializeApp } from "firebase/app" ... const firebaseApp = initializeApp(firebaseConfig) ...
```
現在,我們已經成功地升級了我們的應用程式,以遵循新的v9.x模組化格式。
結論
新的Firebase v9.x SDK由於採用了模組化格式,所以比它的前輩v8.x提供了更快的網路體驗。本教程介紹了新的SDK,並解釋瞭如何使用其緊湊的庫來反映一個React應用。你應該能夠按照本文介紹的方法和步驟,將你自己的應用程序升級到最新版本。
如果你在重構React應用程式時仍有困難,請務必檢視以下Firebase支援社群。
The postRefactor a React app with the new Firebase v9.x Web SDKappeared first onLogRocket Blog.
- 在C 中把字串轉換為整數的兩種簡單方法
- 如何在Flutter中實現任何UI
- Gatsby v4的新內容
- 建立一個Puppeteer微服務以部署到Google Cloud Functions
- 在Blazor中測試。一個完整的教程
- 在React中使用Plotly來構建動態圖表
- 分頁、載入更多按鈕和無限滾動的指南
- 用新的Firebase v9.x Web SDK重構一個React應用
- 在使用地理定位API時,你需要知道什麼?
- 在PostgreSQL v14中,JSON有什麼新功能?
- 使用React的函數語言程式設計的基礎知識
- 使用Dart FFI訪問Flutter中的本地庫
- 使用視訊播放器外掛在Flutter中處理視訊
- 改進過度約束的Rust庫API
- 用Svelte建立一個PWA
- 用Flask和D3.js構建互動式圖表
- 在Go中使用JSON。帶例子的指南
- 一篇文章入門Unix中的AWK命令!
- C 雜湊
- Dotfiles - 什麼是Dotfile以及如何在Mac和Linux中建立它