ทุกอย่างที่ต้องรู้ก่อนใช้ Firebase Local Emulator Suite กับ Cloud Firestore
ถึงแม้ว่าเครื่องมือสำหรับพัฒนาและทดสอบ Firebase app บน Local อย่าง Firebase Local Emulator Suite จะเปิดตัวมานานเป็นปีแล้ว แต่ด้วยความเป็น Serverless backend tools ของ Firebase ที่รวดเร็วปรู๊ดปร๊าด อาจทำให้หลายคนยัง dev on production กันอยู่ (คนจริงเค้าเทสงานบน production กัน ทุกคนรู้ ยูสเซอร์รู้ 😂)
ที่ผ่านมาข้อจำกัดของ Firebase Local Emulator Suite ก็คือ ทุกอย่างต้องทำผ่าน command line แต่คุณคะ เมื่ออาทิตย์ก่อนเพิ่งมีการเปิดตัว Firebase Emulator Suite UI ที่เหมือนยก Firebase Console มาอยู่ใน Local ทำให้เราบริหารจัดการข้อมูลต่างๆ ได้ง่ายขึ้นไปกว่าเดิมอีก แล้วเราจะไม่ใช้ได้หรออออ
บทความนี้ จะพาทุกคนไปลองใช้ Firebase Local Emulator Suite กับการทดสอบข้อมูลใน Cloud Firestore กัน
ทำไมต้องทดสอบบน Local?
- ข้อมูลใน Production ยังคงปลอดภัย ข้อมูลทุกสิ่งแยกออกจากกัน จะไม่มีการเผลอไปลบข้อมูลของผู้ใช้อีกต่อไป
- สะดวกต่อการเขียนเทส เนื่องจากเราสามารถกำหนดเซทของข้อมูลตาม test case ได้เลยตามต้องการ
- ไม่มีค่าใช้จ่ายที่คาดไม่ถึง จากการเพิ่มข้อมูลที่มากเกินไป หรือการเรียกใช้ functions เกินความจำเป็นในขณะที่ทดสอบระบบ
- เขียน Security Rules ได้ง่ายขึ้น แก้ปุ๊บ เห็นผลปั๊บ ไม่ต้องไปกด deploy ให้เมื่อยมือ
#1 เริ่มต้นใช้งาน
สำหรับการสร้างโปรเจคใหม่ (ที่ใช้ Firebase CLI ตั้งแต่ v.8.4.0 ขึ้นไป) จะมีตัวเลือกให้ set up emulator ตั้งแต่การทำ firebase init
ซึ่งเราสามารถเลือก emulator สำหรับ product ที่ต้องการ พร้อมกับทำการเลือก port ให้แต่ละ product ได้เลย
หลังจากจบขั้นตอนการติดตั้ง ถ้าดูในไฟล์ firebase.json จะพบว่ามี config ในส่วนของ emulators เพิ่มเข้ามาด้วย
สำหรับโปรเจคที่ใช้ Firebase อยู่แล้ว สามารถรัน firebase emulators:start
เพื่อเริ่มต้นใช้งานได้เลย โดยที่ไม่ต้องมี emulator config ในไฟล์ firebase.json
ก็ได้ (ซึ่ง emulators จะรันบน default port ที่ Firebase กำหนดไว้)
ถ้าหากต้องการแก้ไข port เราสามารถเพิ่ม emulator config ตามภาพก่อนหน้า เข้าไปในไฟล์ firebase.json
หรือถ้าขี้เกียจพิมพ์เอง สามารถใช้คำสั่ง firebase init emulators
แล้ว set up ผ่าน CLI ก็ได้เช่นเดียวกัน
#2 เชื่อมต่อข้อมูลบน local เข้ากับ app
ท่าง่ายๆ ก็คือ ก่อนจะเรียกใช้ Firestore ให้เช็ค location ก่อน ถ้าเป็น localhost ให้ทำการ config host ของ database โดยชี้ไปที่ host ของ Firestore ที่เราตั้งค่าไว้ในขั้นตอนที่แล้ว
const db = firebase.firestore()
if (location.hostname === "localhost") {
db.settings({ host: "localhost:4001", ssl: false })
}
หรือจะเพิ่มค่า boolean มาสักตัวหนึ่งสำหรับเก็บ flag ว่าต้องการจะใช้ emulator มั้ย ไว้กับ firebase config แล้วเช็คจากค่านั้นแทนการเช็ค location
import firebase from 'firebase/app'
import 'firebase/firestore'
import config from './firebase-config'firebase.initializeApp(config)if (config.useEmulator === true) {
firebase.firestore().settings({
host: 'localhost:4001', ssl: false
})
}
วิธีนี้จะทำให้เราไม่ต้องมาคอย comment code ให้ linting tool อารมณ์เสีย ตอนที่อยากสลับไปเทสข้อมูลบน prodution ในบางที (แต่ไปสลับค่า flag แทน 😂)
#3 start emulator
สำหรับคนที่ทำ static website และใช้ Firebase Hosting สามารถใช้คำสั่ง firebase emulators:start
เพื่อทำการ start local environment ให้กับทุก product ที่เลือกไว้ในขั้นตอนที่ #1 รวมถึงทำการ serve app ของตัวเองบน local ด้วย (แทนการเรียก firebase serve
)
แต่สำหรับคนที่ใช้ Javascript framework อย่าง vue หรือ react ที่มี cli สำหรับ local environment อยู่แล้ว ไม่มีความจำเป็นที่จะให้ firebase serve app บน local ให้ สามารถใช้คำสั่ง--only
เพื่อเลือกใช้ emulator แค่บางตัว เช่น firebase emulators:start --only firestore
แล้วทำการรันคำสั่ง npm run serve
หรือnpm start
เพื่อ start app ของตัวเองในอีกหน้าต่างนึงของ terminal ตามปกติ
ทุกครั้งที่เรา start emulator ใหม่ ข้อมูลใน database จะว่างเปล่าเสมอ ดังนั้นไม่ต้องตกใจ ถ้ารันมาแล้วข้อมูลใน app ของคุณหายไป
เราสามารถทำการเพิ่มข้อมูลใน local ได้หลากหลายวิธี ไม่ว่าจะผ่าน Emulator Suite UI หรือจาก app เองโดยตรง และถ้าต้องการที่จะนำข้อมูลเหล่านั้นมาใช้ในการเทสครั้งถัดไป ก่อนที่จะปิดการใช้งานบน local (stop emulator) ให้ทำการ export ข้อมูลนั้นออกมาก่อน
#4 export ข้อมูล
ก่อนที่เราจะทำการ stop emulator (Ctrl+C) เราสามารถเปิด terminal อีกหน้าต่างนึง เพื่อ export ข้อมูลที่เราเพิ่มไว้ออกมาก่อน ซึ่งสามารถทำได้ด้วยคำสั่ง
firebase emulators:export [FOLDER_NAME]
ซึ่งข้อมูลที่ได้จะเป็นโฟลเดอร์ที่ประกอบไปด้วย โฟลเดอร์ที่ชื่อว่า firestore_export
และไฟล์ firebase-export-metadata.json
#5 import ข้อมูลมาใช้
ตอน start emulator เราสามารถนำเข้าข้อมูลที่เรา export ไว้ ด้วยคำสั่ง import ตามด้วยชื่อโฟลเดอร์ที่ต้องการ
firebase emulators:start --only firestore --import [FOLDER_NAME]
จะเห็นว่า สะดวกกับการสร้างชุดข้อมูล แล้ว import มาใช้ตาม test case ต่างๆ สุดๆ
#6 นำข้อมูลจาก server มาใช้ใน local
สำหรับคนที่เคย dev on production มาก่อน อาจจะต้องการนำข้อมูลใน Firestore บน cloud มาใช้ใน local ก็ทำได้เช่นกัน ด้วยการใช้ gcloud command line tool มาช่วย
1. login แล้วเลือกโปรเจคที่ต้องการ
gcloud auth login
gcloud config set project [YOUR_PROJECT_ID]
2. export ข้อมูลใน Firestore ไปเก็บไว้ใน Cloud storage bucket (จะทำ Step นี้ต้อง enable billing ก่อนนะ)
gcloud firestore export gs://[YOUR_PROJECT_ID].appspot.com/backup/firestore_export
backup/firestore_export
คือ path ที่เราต้องการจะเก็บ สังเกตก็คือเราจะตั้งชื่อให้มันคล้ายกับไฟล์ที่เรา export จาก emulator เพื่อให้ง่ายต่อการ import ใน step ถัดไปนั่นเอง
3. ดาวน์โหลดไฟล์มาเก็บไว้ในเครื่อง
gsutil cp -r gs://[YOUR_PROJECT_ID].appspot.com/backup .
4. import ข้อมูลมาใช้เข้ามาใช้ใน local
ถ้าลองเปิดดูในโฟลเดอร์ที่ดาวน์โหลดมาจะเห็นว่า ไฟล์ที่ได้จะคล้ายๆกับไฟล์ที่เรา export มาจาก emulator เลย แต่เวอร์ชั่นที่เรา export มาจาก emulator จะมีไฟล์ firebase-export-metadata.json
เพิ่มมาด้วย
ดังนั้นให้ทำการเพิ่มไฟล์นี้เข้าไปใน folder backup ที่เราดาวน์โหลดมาก่อน ด้วยวิธีการที่ถนัดอย่าง copy แล้ว paste 😂 หรือจะ run script ที่ command line ด้วยคำสั่ง
echo ‘{“version”:”8.4.2",”firestore”:{“version”:”1.11.4",”path”:”firestore_export”,”metadata_file”:”firestore_export/firestore_export.overall_export_metadata”}}’ > backup/firebase-export-metadata.json
พอมีไฟล์ firebase-export-metadata.json
ในโฟลเดอร์ backup แล้วเราก็สามารถ import ข้อมูลเข้าไปใน emulator ด้วยคำสั่ง import ใน สเตปที่ #5 ได้เลย
#7 นำข้อมูลจาก local ไปใช้ใน server
หรือกลับกัน สำหรับคนที่พัฒนาแบบ local first อาจจะมีความต้องการนำข้อมูลที่เราพัฒนาและทดสอบไว้แล้วใน local เข้าไปใช้ใน server ตอน deploy ระบบ ก็สามารถทำได้ด้วย gcloud command เช่นกัน
1.อัพโหลดโฟลเดอร์ไปเก็บไว้ใน bucket ด้วยคำสั่ง
gsutil cp -r [FOLDER_NAME] gs://[YOUR_PROJECT_ID].appspot.com/
2.นำข้อมูลเข้า Firestore
gcloud firestore import gs://[YOUR_PROJECT_ID].appspot.com/[FOLDER_NAME]/firestore_export
อ่านเพิ่มเติมเกี่ยวกับการ export และ import data ได้ที่
ในขณะที่เขียนบทความนี้ Firebase Local Emulator Suite ยังอยู่ใน Beta stage ซึ่งเชื่อว่าถ้าเป็น GA เมื่อไหร่จะมีความดีงามที่มากกว่านี้แน่ๆ ถ้าใครยังไม่ได้ใช้มาลองใช้ด้วยกันนะคะ หรือใครที่ใช้อยู่แล้วเห็นว่าสามารถพัฒนาเพิ่มเติมได้ตรงไหน ส่ง Tweet ไปบอกกับทีม Firebase ได้น้า หรือจะส่งข้อความมาที่เพจ Firebase Thailand ก็ได้ค่า เราพร้อมเป็นกระบอกเสียงให้คุณ สำหรับวันนี้ขอบคุณและสวัสดีค่า :)