Belajar Dart - Multiplatform & Shared Libraries
Series/Belajar Dart/Episode 17
Episode 17 of 23

Belajar Dart - Multiplatform & Shared Libraries

Episode ini membahas strategi multiplatform dan shared libraries di Dart: berbagi kode antara mobile, web, server, dan CLI, arsitektur modular dengan package yang dapat dipakai ulang, testing cross-platform, serta integrasi dengan Flutter plugins.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Salah satu janji terbesar Dart terwujud ketika kode yang sama berjalan di mobile, web, server, dan command line. Episode 17 membahas strategi multiplatform dan shared libraries: bagaimana memisahkan logika dari platform, menyusun project modular, menguji lintas platform, dan terhubung dengan Flutter plugins.

Kunci semua ini adalah disiplin: kode yang dibagi harus murni dan bebas dependency platform. Kalian akan belajar memisahkan lapisan dengan benar sehingga satu paket logika melayani semua klien.

Berbagi Kode antara Mobile, Web, Server, dan CLI

Lapisan Core yang Murni

Inti strategi multiplatform adalah memisahkan logika bisnis (yang murni Dart) dari detail platform (UI, file, jaringan native):

Struktur project multiplatform
monorepo/
├── packages/domain_core/    # murni Dart, dipakai semua platform
├── apps/flutter_app/        # mobile dan web via Flutter
├── apps/server/             # backend dengan Shelf
└── apps/cli/                # command-line tool

packages/domain_core/ adalah pure Dart package tanpa dependency Flutter atau io spesifik. Setiap aplikasi menambahkan package ini sebagai dependency dan memakai logika yang sama persis di semua platform.

Menjaga Kode Tetap Portable

Agar package bisa dibagi, patuhi aturan: hindari dart:io dan dart:html di lapisan core — keduanya hanya tersedia di sebagian platform. Untuk operasi yang bergantung platform, definisikan abstraksi (interface) di core dan berikan implementasi konkret per platform.

Arsitektur Modular dan Reusable Packages

Monorepo dengan Workspace

Dart mendukung project multi-package dalam satu monorepo. Struktur umum memakai packages/ yang berisi library yang dapat dipakai ulang:

Dependency antar package
name: apps_flutter
dependencies:
  domain_core:
    path: ../../packages/domain_core

domain_core ditambahkan dengan path: sehingga perubahan di package langsung terlihat tanpa publish. Setiap package punya pubspec.yaml dan siklus versioning sendiri.

Menentukan Batas Package

Paket yang baik punya satu tanggung jawab: domain, data access, atau presentasi. Batas yang jelas memungkinkan tim mengerjakan bagian berbeda tanpa saling melangkahi, dan memudahkan pengujian karena dependensi bisa di-mock.

Mulai dengan dua package saja — satu untuk domain dan satu untuk aplikasi — lalu pecah lebih lanjut saat tim dan fitur tumbuh. Batas package yang dipaksakan terlalu dini justru menambah biaya koordinasi tanpa manfaat nyata.

Cross-Platform Testing dan Code Reuse Patterns

Menguji Core Sekali, untuk Semua

Karena semua platform memakai logika yang sama, uji package core sekali dan hasilnya berlaku untuk semua klien:

Menjalankan test package core
cd packages/domain_core
dart test

dart test di package core memvalidasi logika yang dipakai Flutter, server, dan CLI sekaligus. Ini penghematan besar dibanding menulis test terpisah per platform.

Pola Reuse yang Efektif

  • Interfaces sebagai kontrak: definisikan repositori dan service di core, implementasikan di platform.
  • Dependency injection: kirim implementasi konkret saat aplikasi boot.
  • DTO: bagikan model data lewat core agar serialisasi konsisten antar platform.

Kombinasi ketiganya menghasilkan lapisan yang bisa diuji terpisah: repository memakai interface dari core, dan aplikasi menyuntikkan implementasi berbasis HTTP atau database sesuai platform. Alur ini membuat penggantian sumber data tidak menyentuh logika bisnis sama sekali.

Integrasi dengan Flutter Plugins

Memanggil Kemampuan Native

Kebutuhan khusus platform ditangani lewat Flutter plugins. Plugin menggabungkan kode Dart dengan implementasi native Android, iOS, dan lainnya:

Memakai plugin Flutter
import 'package:shared_preferences/shared_preferences.dart';
 
Future<void> simpanPref() async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('tema', 'gelap');
}

SharedPreferences.getInstance() adalah contoh plugin populer yang menyediakan API Dart di atas implementasi native per platform.

Untuk membuat plugin: flutter create --template=plugin. Plugin menghasilkan API Dart di folder lib/, implementasi Android di android/, iOS di ios/, dan seterusnya. Platform channel menghubungkan keduanya. Jika logika platform semakin kompleks, pertimbangkan FFI (episode 16) sebagai alternatif yang lebih portabel.

Karena plugin menyentuh banyak platform, pastikan setiap perubahan diuji di seluruh target. Mulai dari template bawaan, lalu tambahkan fungsionalitas platform satu per satu — ini menjaga plugin tetap kecil dan mudah dipelihara.

Jangan menaruh logika bisnis di dalam plugin. Taruh di package core, dan biarkan plugin hanya menjadi jembatan tipis ke kemampuan native.

Penutup

Inti yang harus dibawa pulang:

  • Pisahkan logika bisnis murni di package core yang bebas dependency platform.
  • Hindari dart:io dan dart:html di lapisan yang dibagi lintas platform.
  • Monorepo dengan packages/ dan dependency path memudahkan pengembangan modular.
  • Test package core sekali; hasilnya berlaku untuk semua klien.
  • Platform-specific capability ditangani lewat abstraksi dan Flutter plugins.
  • Plugin menggabungkan API Dart dengan implementasi native per platform.

Di episode 18 selanjutnya kita akan membahas ekosistem ekstensi dan komunitas — package populer seperti dio, freezed, dan Riverpod, bekerja dengan pub.dev dan publishing package, berkontribusi ke open source Dart, serta sumber belajar dan kanal komunitas.