State of Problems

  • Aplikasi perlu state yang sering berubah.
  • Deploy terlalu mahal, tidak ada waktu untuk integration test.
  • Tim teknikal terbatas, konfigurasi harus bisa di-maintenance oleh non tim-teknis.

Solusi dari masalah di atas idealnya adalah sebuah backoffice yang mengatur konfigurasi dari aplikasi. Tetapi dengan tim yang terbatas, cost untuk membuat backoffice terlalu mahal.

Firebase Remote Config, salah satu fitur gratis yang disediakan Firebase untuk menyelesaikan masalah di atas. Remote config ini bisa digunakan untuk aplikasi mobile maupun web.

Saya akan coba menulis proof of concept bagaimana Firebase Remote Config ini bisa diintegrasikan dengan aplikasi web, tepatnya React dan menggunakan Redux.

Goal dari tutorial ini nantinya adalah bagaimana Remote Config bisa dibaca melalui state redux.

Oke kira-kira, flow yang akan kita buat adalah seperti ini:

Firebase Remote Config -> Redux -> UI

Silahkan menuju ke documentasi firebase langsung untuk menginstall firebase di UI.

Setup Remote Config

Untuk setup inject Remote Config, pastikan bahwa kita telah aktivasi remote Config di dashboard Firebase. Untuk saat ini, hanya tipe data primitif yang di dukung Remote Config.

Firebase Remote Config values

Pertama, yang akan saya lakukan adalah membuat Singleton class untuk Firebase Remote Config.

class RemoteConfig {

  _remoteConfig = null;
  static _instance = null;

  constructor() {
    if (firebase.apps.length === 0) {
      firebase.initializeApp(FIREBASE_CONFIG);
    }
    if (this._remoteConfig === null) {
      this._remoteConfig = firebase.remoteConfig();
      this._remoteConfig.settings = {
        minimumFetchIntervalMillis: 60000, // one minute
        fetchTimeoutMillis: 30000, // 30 seconds
      };
    }
  }

  static get instance() {
    if (RemoteConfig._instance) {
      return RemoteConfig._instance;
    }
    const r = new RemoteConfig();
    RemoteConfig._instance = r;
    return RemoteConfig._instance;
  }

}

Note, di sini ada dua setting yang saya pakai:
minimumFetchIntervalMillis: Lama waktu yang diperlukan untuk refresh konfigurasi paling baru dalam miliseconds. Di sini saya pakai 60 detik.

fetchTimeoutMillis: Lama waktu timeout untuk fetching Remote Config dalam miliseconds. Di sini saya pakai 30 detik.

_remoteConfig: Adalah instance dari Firebase Remote Config.

Deserialize Remote Config

Remote Config cukup di fetch sekali lalu kita simpan di state untuk pemakaian selanjutnya di aplikasi.

Nah, jika kita fetching berkali-kali, Firebase akan men-throttle aplikasi kita sampai 24 jam. Tentu, kita tidak mengharapkan itu bukan?

Selanjutnya saya akan melakukan deserializing untuk data firebase yang telah berhasil di fetch. Firebase by default memberikan object RemoteConfig jika berhasil.

  get values() {
    return new Promise(async (resolve, reject) => {
      try {
        const firebaseRemoteConfig = RemoteConfig.instance._remoteConfig;
        await firebaseRemoteConfig.fetchAndActivate();
        const _values = firebaseRemoteConfig.getAll();
        if (_values) {
          resolve({
            "title": _values["title"].asString(),
            "showBustton": _values["showButton"].asBoolean(),
            "loop": _values["loop"].asNumber(),
          })
          return;
        }
        resolve(RemoteConfig.deffault);
      } catch (e) {
        resolve(RemoteConfig.deffault);
      }
    });
  }

Okey, saya juga akan menyediakan fallback default value jika fetching tidak berhasil. Dan sebaiknya memang seperti itu.

  static default = {
    "title": "My Remote Config Proof of Concept Default",
    "showButton": false,
    "loop": 3,
  };

Sehingga class RemoteConfig kita sekarang seperti:

class RemoteConfig {

  _remoteConfig = null;
  static _instance = null;

  static default = {
    "title": "My Remote Config Proof of Concept Default",
    "showButton": false,
    "loop": 3,
  };

  constructor() {
    if (firebase.apps.length === 0) {
      firebase.initializeApp(FIREBASE_CONFIG);
    }
    if (this._remoteConfig === null) {
      this._remoteConfig = firebase.remoteConfig();
      this._remoteConfig.settings = {
        minimumFetchIntervalMillis: 60000, // one minute
        fetchTimeoutMillis: 30000, // 30 seconds
      };
      this._remoteConfig.defaultConfig = RemoteConfig.deffault;
    }
  }

  static get instance() {
    if (RemoteConfig._instance) {
      return RemoteConfig._instance;
    }
    const r = new RemoteConfig();
    RemoteConfig._instance = r;
    return RemoteConfig._instance;
  }

  get values() {
    return new Promise(async (resolve, reject) => {
      try {
        const firebaseRemoteConfig = RemoteConfig.instance._remoteConfig;
        await firebaseRemoteConfig.fetchAndActivate();
        const _values = firebaseRemoteConfig.getAll();
        if (_values) {
          resolve({
            "title": _values["title"].asString(),
            "showBustton": _values["showButton"].asBoolean(),
            "loop": _values["loop"].asNumber(),
          })
          return;
        }
        resolve(RemoteConfig.deffault);
      } catch (e) {
        resolve(RemoteConfig.deffault);
      }
    });
  }

}

Setup Redux State & UI

Sebelum di pakai UI, agar pemakaian effisien kita akan menyimpan konfigurasi dari remote config di Redux state.

export const injectRemoteConfig = (remoteConfig) => {
  return {
    type: INJECT_REMOTE_CONFIG,
    payload: remoteConfig,
  }
};

const remoteConfigReducer = (state = {}, action) => {
  switch (action.type) {
    case INJECT_REMOTE_CONFIG: return { 
      ...state, remoteConfig: action.payload
    };
    default: return state;
  }
}

Di bagian UI, sebelum kita akan inject remote config di root App component. Tepat setelah component mounting.

  componentDidMount() {
    RemoteConfig.instance.values.then((v) => {
      this.props.injectRemoteConfig(v);
    })
  }

Voalla!! Firebase Remote Config sudah kita inject ke Redux State dan siap digunakan UI.


Okey. Aplikasi keseluruhan contoh di atas bisa kamu pelajari di Github saya di https://github.com/codxse/my-reactjs-projects/tree/master/remote-config

Enjoy! semoga membantu