Firebase 教學 - Node.js 操作 Realtime Database

Firebase 除了可以讓網頁前端擁有基本資料庫的能力,也可以使用 Node.js 在後端運行,這篇文章將會描述如何透過 Node.js 操作 RealTime Database,最後還會把程式碼部署到 Google Cloud functions,一氣呵成的實現透過 http request 串接 Realtime Database 的實用範例。

延伸閱讀:

安裝 Node.js 相關模組

使用 Node.js 操作 Firebase 就跟網頁前端一樣簡單,在網頁前端僅需載入對應的 JavaScript,而 Node.js 裏頭僅需引用對應的模組即可,安裝套件的指令如下,首先建立並初始化一個 Node.js 專案。

$ npm init

接著安裝 firebase 模組

$ npm install --save firebase

使用時 require firebase 模組,並宣告一個變數進行 firebase 初始化,初始化的內容和網頁前端幾乎相同,宣告資料庫的網址就能操作操作 Realtime database。

var firebase = require('firebase');
var app = firebase.initializeApp({
    databaseURL: 'https://XXXXX.firebaseio.com/'
});

透過 http request 操作 RealTime Database

透過 Node.js 內建的http 模組,可以建立個接收 http request 的 server,搭配內建的url 模組,就能將收到的資料訊息轉換為物件格式,比較需要注意的地方有兩個:

下方的程式碼執行後,就會啟動一個本地端的 server,這時只要在網址列輸入https://網址?databaseUrl=XXX&type=push&ref=XXX&data=XXX就能將資料寫入到資料庫裡,在網址列輸入https://網址?databaseUrl=XXX&type=read&ref=XXX就能讀取資料庫資料。

const http = require('http');
const url = require('url');

const firebase = require('firebase/app');
require('firebase/database');

const server = http.createServer((req, res) => {
    if (req.url !== '/favicon.ico') {  // 因接收時會一併取得 undefined 的 facicon.ico,使用簡單的邏輯排除
        const params = url.parse(req.url, true).query; //取得網址每個參數
        const ref = params.ref || '/';
        const type = params.type || 'set';
        const data = params.data;
        // 發送 https://網址?databaseUrl=XXX&type=push&ref=XXX&data=XXX 就可寫入資料
        // 發送 https://網址?databaseUrl=XXX&type=read&ref=XXX 就可讀取資料

        const opt = { 
            databaseURL: `https://${params.databaseUrl}/`
        };
        const app = firebase.initializeApp(opt); // firebase 初始化
        const database = app.database();

        switch (type) {  // 依據不同的參數寫入或讀取資料
            case 'push':
                database.ref(ref).push(data).then(() => {
                    res.end(`push data to "${ref}" ok`);
                    firebase.app().delete(); // 寫入完成後刪除 firebase 宣告
                });
                break;
            case 'set':
                database.ref(ref).set(data).then(() => {
                    res.end(`set data to "${ref}" ok`);
                    firebase.app().delete(); // 寫入完成後刪除 firebase 宣告
                });
                break;
            case 'read':
                database.ref(ref).once('value', e => {
                    let dataObj = e.val();
                    let html = '';
                    for (let i in dataObj) {
                        html = `${html}<div>${dataObj[i]}</div>`;
                    }
                    console.log(e.val());
                    res.end(html);
                }).then(() => {
                    firebase.app().delete(); // 讀取完成後刪除 firebase 宣告
                });
                break;
        }
    }
});
server.listen(5000);

部署到 Google Cloud Functions

已經能在本地端運行 Node.js 服務並操作 Realtime database 之後,下一步就是將這組程式部署到 Google Cloud Functions 裡,登入 Google 並進入 GCP ( Google Cloud Platform ) 後,在右方選單選擇 Cloud Functions。

對於 Google Cloud Functions 不了解的可以參考我的這篇文章:簡易後端實作 ( Google Cloud Functions )

如果第一次使用會要求輸入信用卡資訊 ( 不用太擔心,像我們這種小咖用戶非常不容易超過免費的額度 ),輸入完成後就可以建立一個專案,專案建立後就新建一組函式,輸入函式名稱以及選擇 128 MB 記憶體。

設定時選擇 Node.js 版本為 8,並開始編輯程式,在 index.js 的區域輸入下方程式碼,程式碼和上面介紹的大同小異,差別在於執行函示改成 helloWorld,並在一開始的時候使用setHeader做跨域設定。

const url = require('url');
const firebase = require('firebase/app');
require('firebase/database');

exports.helloWorld = (req, res) => { 
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');

if (req.url !== '/favicon.ico') {
    const params = url.parse(req.url, true).query;
    const databaseUrl = `https://${params.databaseUrl}/`;
    const ref = params.ref || '/';
    const type = params.type || 'set';
    const app = firebase.initializeApp({ databaseURL: databaseUrl });
    const database = app.database();
    const data = params.data;
    switch (type) {
        case 'push':
            database.ref(ref).push(data).then(() => {
                res.status(200).send(`push data to "${ref}" ok`);
                firebase.app().delete();
            });
            break;
        case 'set':
            database.ref(ref).set(data).then(() => {
                res.status(200).send(`set data to "${ref}" ok`);
                firebase.app().delete();
            });
            break;
        case 'read':
            database.ref(ref).once('value', e => {
                let dataObj = e.val();
                let html = '';
                for (let i in dataObj) {
                    html = `${html}<div>${dataObj[i]}</div>`;
                }
                console.log(e.val());
                res.end(html);
            }).then(() => {
                firebase.app().delete();
            });
            break;
        }
    }
};

修改 package.json 的內容,讓部屬時會自動安裝 firebase 模組。

{
    "name": "sample-http",
    "version": "0.0.1",
    "dependencies": {
        "firebase": "^6.3.0"
    }
}

完成後按下「建立」,就會開始部署程式,部署成功會看見函式前方出現綠色的勾勾圖示,在觸發條件的頁籤裡也會看見最終部署的網址。

在瀏覽器輸入網址並後方加上參數,執行後就會寫入資料到資料庫,或是從資料庫讀取資料囉~

小結

透過 Node.js 搭配 Google Cloud Functions,就能輕鬆實現透過 http request 存取 Firebase Realtime database 的功能,也就更加方便實用囉~

參考:Firebase - npm

有興趣瞧瞧其他新文章嗎?