Yish
Yish
Nov 22, 2018 · 8 min read

應用架構設計

前一篇 QRCode Scanner with VueJS 大概講述了 QRCode Scan 的主要設計狀況,這篇文章將會繼續探討 firestore 在後面運作方式與設計以及 firestore 的操作和 deploy。

具體的細節應用架構如下圖:

邏輯層

這邊採用 vue cli 去建立應用,會選用的原因除了整合度高,可以自選調用組件跟生態系,搭配 vuetify 這個組件把外觀跟設定統一達到開發效率高。

Build Web Apps with Vue JS 2 & Firebase | Udemy
Vue Vuex Firebase Messaging App (Slack Clone) | Udemy

由於每個專案和情境都不太相同,這邊不多作贅述和深入探討 vue cli 等配置方式。

Authentication

由於我們給廠商使用時必須有權限限制存取,使用了 firebase 當中的權限存取,就是提供了許多方式作身分驗證,詳細可以看 Firebase Authentication | Firebase

如果對於登入驗證實作細節代碼有興趣可以拜訪:
Authentication With Firebase and Vue router
Keeping firebase login stats with vuejs

Cloud Firestore

db.collection("users").doc(uid).get().then(doc => {
let user = doc.data();
this.user = {
name: user.name,
email: user.email,
};
});

Get data with Cloud Firestore | Firebase

collection 指的是節點,類似叢集,例如有 users 這個 collection 底下會有很多的資料,doc 是透過節點下的 key 去取得資料,接著透過 then,作各種取得資料,比較特別的是 get() 可以透過帶入 type 去決定取得方式 Interface: GetOptions | Firebase 預設如果伺服器沒辦法拜訪則會返回 cache,反之則會去取得,可以依照自己情境作調用。

這邊將資料取回後放入 vue.js 的 data 當中作 observe 方便後續存取更新。

當然可以一次取得 collection 下面的所有 documents,像是這樣:

db.collection("users").get().then(querySnapshot => {
querySnapshot.forEach(doc => {
console.log(doc.id, " => ", doc.data());
});
});

其他細節可以參考官方網站文件 Get data with Cloud Firestore | Firebase

Add or Set?

兩者之間的差異文件上有段簡單的描述:
Add data to Cloud Firestore | Firebase

When you use set() to create a document, you must specify an ID for the document to create.

意思是如果你用 set() 你必須去指定 id,反之如果你希望由 firebase 自動產生出 id 可以透過 add() 新建資料。

sometimes there isn’t a meaningful ID for the document, and it’s more convenient to let Cloud Firestore auto-generate an ID for you. You can do this by calling add():

關於更多的資料操作可以參考文件。

Get realtime updates

Firestore 最強大的特性是可以動態的取得資料並即時更新,如同 node.js + socket.io 透過 websocket,只是 client 與 server 端的 api 都已經幫你準備好了,他會在連結後建立監聽來確保資料同步。

Get realtime updates with Cloud Firestore | Firebase

db.collection("users").doc("Yish")
.onSnapshot(doc => {
console.log("Current data: ", doc.data());
});

支持監聽與各式操作監聽:

db.collection("users").onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type === "added") {
console.log("new user:", change.doc.data());
}
if (change.type === "modified") {
console.log("Modified user: ", change.doc.data());
}
if (change.type === "removed") {
console.log("Removed user: ", change.doc.data());
}
});
});

小技巧

在某些特定情境下,假如 users/yish/events 我必須監聽底下所有的內容更新狀態,可以透過 doc.ref 持續往底下監聽或查找:

db.collection("users").onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
// 第一次呼叫
if (change.type === "added") {
console.log("new user:", change.doc.data());
}
// 更新修改
if (change.type === "modified") {
console.log("Modified user: ", change.doc.data());
}
// 確保檔案不會上下影響,是監聽下層
if (change.type !== "modified") {
change.doc.ref.collection("events")
.onSnapshot(querySnapshot => {
//do what you need
}
}
});
});

Firestore Rule

Firestore 節點規則可以限制存取節點,像是 users 可以讀取,但如果需要寫入則必須登入:

service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow read: if true;
allow write: if request.auth.uid != null;
}
...
}

介面上也有提供對應的模擬工具,可以在正式寫之前模擬一下再把他寫在 firestore.rules

Firebase tools

GitHub — firebase/firebase-tools: The Firebase Command Line Tools
可以透過 google 提供的 工具進行佈署和 initial project。

小貼士

假定我們有一組活動有很多場次,譬如:

  • 1:00~2:00
  • 2:00~3:00
  • 4:00~5:00

時間到期時場次必須消失隱藏,但問題出現在剛剛我們的情況都會是在監聽資料的變化性,也就是觸發點是 firestore 接收到動作後去更新修改資料,但 client 如果是資料到期則無法更新,也就是說主動權是在 firestore on snapshot 上面,依照上面的情境我們可以使用:

// 設定一個 timer
data() {
return {
timer: null
};
// 每秒輪詢場次是否到期
created() {
this.timer = setInterval(() => {
this.events.forEach(event => {
event.sessions.forEach(session => {
this.isSessionExpired(session);
})
});
}, 1000)
}
// 執行完清除 timer
destroyed() {
clearInterval(this.timer);
},

取得資料建議從 created 取得在依序透過綁定方式放到 vue.js 當中,主要是 vue.js 生命週期的設計,可以參考 The Vue Instance — Vue.js

後記

這邊主要放在 firebase/firestore 的說明而不是放在 vue.js 當中是因為 vue.js 邏輯層會因為需求不同而會有截然不同的寫法,這次的專案我採用了 vuetify 這個 component framework 主要是需求方並沒有要求外觀並且強調易用性,所以採用這套以 material design 為基礎,並且與 vue.js 高度整合的框架,配合上 vue cli 3 的整合性和 firebase tools 提供的接口,快速開發和實作項目。

下一篇我們將討論 firestore cloud functions 與 algolia 如何整合達到 full-text search 的功能,Cheers 🎉

Parenting Engineering

《親子天下雜誌》創刊於2008年8月,為華文圈影響力最大的教育教養品牌,也是最值得信賴的親子社群平台。希望提供給學校和家庭,專業可信賴的教育教養解決方案。從線上(online)到實體(offline),分齡分眾供應華人地區親子家庭最合身體貼的優質內容、活動、產品與服務。

Yish

Written by

Yish

Never stop progressing. https://yish.dev

Parenting Engineering

《親子天下雜誌》創刊於2008年8月,為華文圈影響力最大的教育教養品牌,也是最值得信賴的親子社群平台。希望提供給學校和家庭,專業可信賴的教育教養解決方案。從線上(online)到實體(offline),分齡分眾供應華人地區親子家庭最合身體貼的優質內容、活動、產品與服務。

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade