freedomlife: Teknologi Di Balik Layar

19 Juni 2024  •  --------

Tersedia dalam .

Sebelumnya saya sudah membahas di balik layar freedomlife secara general. Nah, di tulisan kali ini saya akan membahas di balik layar freedomlife secara teknis. Maka dari itu, tulisan ini akan fokus membahas bagaimana freedomlife dibuat, dan teknologi-teknologi yang digunakan.

Tech Stack

Awal

Awalnya, saat pertama kali freedomlife dibuat (2019-2020), aplikasi ini hanya tersedia di web saja yang dibangun menggunakan Next.js. Saat itu karena material design sedang hangat-hangatnya, saya memutuskan untuk menggunakan Material-UI component library sebagai style system. Data panduan dan Alkitab yang digunakan, disimpan di dalam sebuah MongoDB database.

Tema Basic
Tema Valentine
Tema Natal

Sekarang

Karena aplikasi freedomlife berkembang, kini aplikasi ini tidak hanya tersedia di web saja, namun juga tersedia di iOS & Android. Maka, terjadi perubahan dalam tech stack nya. Saat ini saya menggunakan Next.js & Expo.

Basis dari dua framework tersebut adalah React. Selain terkenal sebagai UI library untuk web, React juga dapat berjalan di berbagai platform lainnya. Expo menggunakan React Native yang memungkinkan React untuk berjalan secara native di iOS & Android (bahkan juga di macOS & Windows).

Karena kebutuhan bergeser, saya harus menggunakan style system yang lebih universal, yang dapat berjalan cross-platform di web, iOS dan Android. Pilihan saya jatuh kepada NativeWind. Karena NativeWind menggunakan Tailwind CSS di dalamnya, sehingga memudahkan saya yang sudah familiar dengan atomic classes yang dimiliki Tailwind.

Tentu dengan berkembangnya aplikasi, data Alkitab yang dibutuhkan juga semakin banyak. Yang awalnya hanya tersedia satu versi saja, sekarang tersedia beberapa versi dalam bahasa Indonesia dan Inggris.

Hal ini membuat saya membutuhkan database yang relasional yang juga menyediakan layanan database secara cloud. Saya memilih Supabase yang memiliki PostgreSQL database dan storage yang cocok untuk use-case freedomlife.

Arsitektur

Awal

Pertama kali aplikasi ini dibuat, arsitekturnya sederhana. Seperti sudah disebutkan sebelumnya, freedomlife hanya sebuah aplikasi Next.js yang di host di Vercel. Next.js memungkinkan saya untuk membangun freedomlife secara full-stack yang frontend dan backend nya ada di dalam satu codebase yang sama menggunakan API Routes.

Sekarang

Arsitektur aplikasi freedomlife sekarang menjadi sebuah monorepo. Saya menggunakan yarn workspaces dan Turborepo untuk mengelola monorepo ini.

yarn workspaces dipilih karena Expo menyediakan first-class support untuk masalah-masalah yang akan terjadi jika menggunakan Expo dengan yarn workspaces (Yarn v1 classic).

Gambaran sederhana arsitektur freedomlife:

Kelebihan Monorepo

  • Reusability — Komponen-komponen yang ditulis dapat digunakan di dua platform sekaligus (web & native). Menurut saya, ini membuat saya lebih mudah mengelolanya.
  • One Dependency — Penggunaan satu versi dependency/library yang sama di antara dua platform. Ini membuat saya lebih mudah mengetahui masalah yang ada di sebuah library, memperbaikinya, maupun menggantinya dengan library lain.
  • Isolated Changes — Arsitektur seperti ini mengubah pola bekerja saya menjadi melakukan perubahan secara bertahap (kecil-kecil) daripada perubahan yang langsung berskala besar. Perubahan kecil dan terisolasi juga memudahkan saya untuk melakukan rollback jika terjadi masalah.

Kekurangan Monorepo

  • Complexity — Repotnya membangun sebuah project monorepo ada di awal saat setup untuk pertama kali. Maka dari itu saya menggunakan tool seperti Turborepo untuk membuat setup nya lebih mudah dan straightforward.
  • Tooling Overhead — Walaupun banyak template dan boilerplate yang tersedia, membuat template tersebut sesuai dengan yang kita perlukan memerlukan waktu dan tenaga tambahan. Diluar hal tersebut saya juga harus belajar bagaimana mengelola dependencies di dalam monorepo, mengubah cara saya menulis kode agar tidak menimbulkan masalah circular dependency.

Data

Saat ini, freedomlife hanya memiliki 2 skema data: Alkitab dan panduan. Data tersebut disimpan di Supabase database. Untuk mendapatkan data tersebut saya membangun API endpoint yang tersedia di /api/guide untuk panduan dan /api/bible untuk Alkitab.

Seperti yang sudah saya ulas di tulisan sebelumnya, data panduan bersumber dari Gereja Kristen Kemah Daud Yogyakarta. Sementara, data Alkitab bersumber dari alkitab.mobi dan juga YouVersion bible. Pengambilan data Alkitab terinspirasi dari project Alkitab API yang dibuat oleh Sonny Lazuardi.

Agar data Alkitab juga dapat diunduh, saya juga menyimpan data Alkitab berbentuk JSON yang lalu disimpan di Supabase storage.

Bagian-Bagian Kode

Menangani Perbedaan Platform

Di dalam sebuah project monorepo, ada kalanya saya juga harus menangani perbedaan platform. Ada kode yang hanya dikhususkan untuk web, atau hanya untuk native. Untuk menangani perbedaan ini, Expo sudah menyediakan konfigurasi webpack yang dapat diintegrasikan dengan Next.js disini. Saya juga perlu menginstall library react-native-web yang di maintain oleh Necolas (Meta) supaya React Native juga dapat berjalan di web dan menangani perbedaan platform tersebut.

Contohnya saat saya ingin membuat sebuah component yang berbeda implementasinya di web dan native, saya dapat menggunakan suffix .web di akhir nama file. Misalnya:

index.tsx
export default function Text() {
  return (
    <View>
      <Text>iOS & Android</Text>
    </View>
  )
}
index.web.tsx
export default function Text() {
  return (
    <div>
      <p>Web only!</p>
    </div>
  )
}

Hal ini juga dapat dilakukan diluar component. Misalnya seperti di kode freedomlife, ada use-safe-area hook untuk mengukur area yang aman untuk menampilkan sesuatu. Hook tersebut sebenarnya hanya saya butuhkan di native app, dan di web tidak saya gunakan. Jadi saya bisa menuliskannya seperti ini:

use-safe-area.ts
import { useSafeAreaInsets } from 'react-native-safe-area-context'

const useSafeArea = useSafeAreaInsets

// Nama dan bentuk exportnya harus sama.
// Jika `export default`, kode yang lain juga harus menggunakan `export default`
export { useSafeArea }
use-safe-area.web.ts
// Nama dan bentuk exportnya harus sama.
// Jika `export default`, kode yang lain juga harus menggunakan `export default`
export function useSafeArea() {
  return {
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
  }
}

Kode implementasi use-safe-area di atas, bisa Anda lihat disini.

Features

Saya mengelompokan setiap halaman di dalam folder features. Ini adalah metode yang saya ambil dari library Solito, freedomlife juga menggunakan library ini. Semua entrypoint baik di web maupun native app akan memanggil halaman yang ada di folder ini. Kurang lebih seperti ini contohnya:

./apps/web/pages/index.tsx & ./apps/native/app/(tabs)/index.tsx
// Entry point
import HomeScreen from '@repo/app/features/home'

export default HomeScreen
./packages/app/features/home/index.tsx
export default function HomeScreen() {
  return (
    <View>
      <Text>Home Screen</Text>
    </View>
  )
}

Jika dibutuhkan, semua halaman yang ada di dalam features dapat juga menangani perbedaan platform dengan menggunakan prefix seperti penjelasan sebelumnya.

Components

Di freedomlife, kode yang dikelompokan dalam bagian ini merupakan bagian-bagian kecil yang sedikit atau bahkan tidak memiliki logic sama sekali di dalamnya — semi-pure dan pure components saja. Komponen ini dapat digunakan kembali (reusable) oleh web maupun native. Silakan lihat beberapa contohnya disini.

Utilities

Yang terakhir, semua kode yang berhubungan sebagai pendukung ada disini. Termasuk implementasi use-safe-area yang ada di bagian sebelumnya.

Deployment

Web

Saya menggunakan Vercel sebagai deployment platform untuk versi web. Seperti yang sudah saya jelaskan di atas, saya menggunakannya sudah sejak dari awal freedomlife dibuat. Vercel mengotomatisasikan proses CI/CD sehingga saya dapat fokus membangun project ini. Untuk database & storage saya menggunakan layanan Supabase cloud.

iOS & Android

Saat saya ingin melakukan native app deployment, saya mencari yang fiturnya mirip dengan Vercel. Bisa mulai dengan gratis, dan dapat mengotomatisasikan proses-proses yang ada. Karena proses deployment native app itu sulit dan memakan banyak waktu. Setelah mencari, saya menemukan bahwa semua hal tersebut dapat dilakukan oleh EAS (Expo Application Services).

  • EAS Build — Mengotomatisasikan proses build kode freedomlife menjadi iOS & Android app.
  • EAS Submit — Mengotomatisasikan proses submit ke Apple App Store & Google Play Store.
  • EAS Update — Memungkinkan saya untuk melakukan over-the-air updates (perbaikan bug kritikal maupun trivial) ke aplikasi yang sudah terinstall di gawai pengguna.

EAS membuat native app deployment serasa seperti web deployment. Mudah, cepat, dan efisien. Saya merekomendasikannya jika Anda ingin mencoba.

Penutup

Jika Anda tertarik untuk mengetahui lebih dalam, source code aplikasi freedomlife terbuka untuk publik dan dapat diakses melalui GitHub. Jika Anda memiliki saran juga bahkan ide-ide untuk aplikasi freedomlife, feel free untuk menaruhnya di GitHub issue.

Akhir kata, bagi saya tidak ada teknologi yang sempurna, jadi saya memilih menggunakan teknologi yang saya bisa berdamai dengan kekurangannya. 😄