Cara Setup Sharing Dependencies untuk Menghemat Resource Server

Tulisan ini saya susun untuk catatan saya sendiri, dan mungkin semoga saja bisa bermanfaat bagi yang membaca tulisan ini. Latar belakang saya dalam menulis tulisan ini sebenarnya muncul karena saya memiliki beberapa proyek portofolio yang dibuat dengan Laravel, dan saya ingin mendeploynya ke server.

Dalam dunia pengembangan web modern, Laravel telah menjadi salah satu framework PHP paling populer karena kemudahan, struktur yang rapi, dan ekosistemnya yang kaya. Namun, di balik kemudahan itu, ada satu tantangan teknis yang sering luput dari perhatianβ€”penggunaan inode yang sangat tinggi, terutama saat mengelola banyak proyek Laravel dalam satu server.

Setiap proyek Laravel secara default akan meng-install ribuan file kecil di folder vendor/, yang berisi semua dependency dari Composer. Di lingkungan shared hosting atau VPS dengan batas inode yang ketat, ini bisa menjadi masalah serius: proyek gagal di-deploy, file tidak bisa ditulis, atau bahkan server menjadi tidak responsif.

Artikel ini membahas pendekatan praktis untuk mengatasi masalah tersebut: membagi dependency inti Laravel ke satu folder global, lalu menghubungkannya ke masing-masing proyek dengan symlink. Dengan strategi ini, kita bisa:

  • Menghemat ribuan inode per proyek
  • Menjaga konsistensi dependency antar proyek
  • Tetap fleksibel untuk kebutuhan spesifik tiap aplikasi

Pendekatan ini sangat cocok untuk developer yang mengelola banyak proyek Laravel di satu server, baik untuk klien, staging, maupun internal tools. Di artikel ini, kita akan membahas konsepnya, langkah setup, struktur folder, dan tips tambahan agar implementasi tetap modular dan maintainable.

Apa Itu Inode?

Inode (index node) adalah struktur data di sistem file Linux yang menyimpan informasi tentang sebuah file atau folderβ€”bukan isi file-nya, tapi metadata-nya.

πŸ” Inode menyimpan:

  • Lokasi file di disk
  • Ukuran file
  • Tanggal dibuat/dimodifikasi
  • Permission dan owner
  • Jumlah hard link

Setiap file atau folder yang dibuat akan menggunakan 1 inode. Jadi kalau kamu punya 10.000 file kecil (misalnya dari vendor/ Laravel), itu berarti 10.000 inode terpakai.

⚠️ Kenapa Inode Penting?

Di banyak server (terutama shared hosting), jumlah inode dibatasi. Kalau kamu kehabisan inode:

  • Tidak bisa membuat file/folder baru
  • Composer gagal install dependency
  • Upload file ditolak
  • Server bisa jadi lambat atau error

πŸ“Š Contoh Kasus Laravel

Folder vendor/ Laravel bisa berisi 10.000+ file kecil. Kalau kamu punya 5 proyek Laravel:

  • Tanpa optimasi: 5 Γ— 10.000 = 50.000 inode
  • Dengan shared dependencies: bisa hemat hingga 80–90% inode

Dengan memahami inode, kita bisa lebih bijak dalam mengelola struktur proyek dan deployment. Selanjutnya, kita akan bahas bagaimana konsep layered dependency sharing bisa jadi solusi modular dan hemat inode.

Konsep Dasar: Layered Dependency Sharing

Setiap proyek Laravel bergantung pada ratusan hingga ribuan file dependency yang di-install melalui Composer ke dalam folder vendor/. Di balik kemudahan ini, ada satu konsekuensi: boros inode. Jika kamu mengelola banyak proyek Laravel dalam satu server, setiap vendor/ akan mengulang isi yang hampir samaβ€”terutama untuk dependency inti seperti laravel/framework, guzzlehttp/guzzle, dan symfony/*.

πŸ”„ Masalahnya:

  • Setiap proyek menyimpan salinan penuh dependency yang sama.
  • Composer tidak dirancang untuk berbagi vendor/ antar proyek secara default.
  • Akibatnya, ribuan file kecil terduplikasi di setiap proyek β†’ pemborosan inode.

πŸ’‘ Solusinya: Layered Dependency Sharing

Alih-alih membiarkan setiap proyek menyimpan semua dependency, kita bisa membagi dependency menjadi dua lapisan:

  1. Core Dependencies (Shared)
    • Dependency yang umum dan stabil di semua proyek.
    • Disimpan di satu folder global (misalnya ~/laravel-core-deps/).
    • Diakses oleh semua proyek melalui symlink.
  2. Project-Specific Dependencies (Local)
    • Dependency unik yang hanya dibutuhkan oleh proyek tertentu.
    • Tetap di-install di folder proyek masing-masing.
    • Composer tetap bisa menambahkan dependency baru tanpa mengganggu core.

🧩 Analogi Sederhana

Bayangkan kamu punya 5 toko yang semuanya butuh rak, meja, dan lampu yang sama. Daripada membeli 5 set lengkap untuk setiap toko, kamu bisa menyimpan satu gudang pusat untuk barang-barang umum, lalu setiap toko hanya menyimpan barang tambahan yang unik.

βœ… Keuntungan Pendekatan Ini

  • Hemat inode secara signifikan (hingga 80–90% dari total vendor).
  • Konsistensi antar proyek: dependency inti selalu sama.
  • Fleksibel: proyek tetap bisa punya kebutuhan unik.
  • Modular dan maintainable: cocok untuk tim atau solo developer dengan banyak proyek Laravel.

Langkah Persiapan: Menyiapkan Folder Core Dependencies

Sebelum kita mulai menghubungkan proyek Laravel ke dependency bersama, kita perlu membuat satu folder khusus yang akan menjadi pusat dependency inti. Folder ini akan menyimpan semua package yang umum digunakan di berbagai proyek Laravel.

1. Buat Folder Global untuk Core Dependencies

Pilih lokasi yang mudah diakses oleh semua proyek, misalnya di home directory:

mkdir ~/laravel-core-deps
cd ~/laravel-core-deps
Bash

2. Inisialisasi Composer dan Install Dependency Inti

Buat file composer.json yang hanya berisi dependency inti yang ingin dibagikan:

composer init
Bash

Tambahkan package Laravel dan dependency umum:

composer require laravel/framework:^10
composer require guzzlehttp/guzzle
composer require fruitcake/laravel-cors
Bash

Kamu bisa menyesuaikan daftar ini sesuai kebutuhan proyek-proyekmu.

3. Validasi Instalasi

Pastikan folder vendor/ dan file autoload.php berhasil dibuat:

ls vendor/
ls vendor/autoload.php
Bash

Jika semua sudah terpasang, folder ini siap digunakan sebagai sumber shared dependency.

4. Catatan Versi dan Konsistensi

  • Pastikan semua proyek Laravel yang akan menggunakan folder ini kompatibel dengan versi Laravel dan package yang di-install.
  • Jika ada proyek yang butuh versi berbeda, kamu bisa membuat folder core terpisah:
~/laravel-core-deps-l9/
~/laravel-core-deps-l10/
Bash

Setup Symlink ke Proyek Laravel

Setelah folder laravel-core-deps/ selesai diisi dengan dependency inti, langkah berikutnya adalah menghubungkan proyek Laravel agar menggunakan dependency tersebut tanpa menyimpan salinan sendiri. Kita akan menggunakan symlink (symbolic link) untuk mengarahkan proyek ke folder vendor/ global.

1. Masuk ke Folder Proyek

Contoh untuk proyek projectA:

cd ~/projectA
Bash

2. Hapus Folder Vendor Lokal

Pastikan tidak ada folder vendor/ yang tersisa:

rm -rf vendor
Bash

3. Buat Folder Vendor dan Symlink Package Core

Daripada menautkan seluruh folder vendor/, kita akan membuat symlink untuk setiap package inti agar lebih fleksibel:

mkdir vendor
ln -s ~/laravel-core-deps/vendor/laravel vendor/laravel
ln -s ~/laravel-core-deps/vendor/guzzlehttp vendor/guzzlehttp
ln -s ~/laravel-core-deps/vendor/fruitcake vendor/fruitcake
ln -s ~/laravel-core-deps/vendor/autoload.php vendor/autoload.php
...
Bash

Ulangi langkah ini untuk setiap proyek Laravel yang ingin menggunakan dependency bersama.

4. Validasi Autoload dan Artisan

Setelah symlink dibuat, pastikan Laravel bisa berjalan normal:

php artisan --version
php artisan config:cache
Bash

Jika tidak ada error, berarti autoload berhasil membaca dependency dari symlink.

5. Tambahkan Dependency Spesifik (Jika Ada)

Jika proyek butuh package tambahan, cukup jalankan:

composer require barryvdh/laravel-dompdf
Bash

Composer akan menambahkan package baru ke vendor/ proyek tanpa mengganggu symlink yang sudah ada.

πŸ“Œ Tips Tambahan

  • Jangan symlink seluruh folder vendor/ sekaligus, karena bisa bentrok dengan file lokal.
  • Pastikan vendor/autoload.php tetap ada di masing-masing proyek.
  • Gunakan script bash untuk automasi symlink jika proyek banyak.

Struktur Folder Final: Core Shared + Proyek Modular

Setelah semua langkah dijalankanβ€”menyiapkan folder core, membuat symlink, dan menambahkan dependency spesifikβ€”struktur folder proyek akan terlihat seperti ini:

/home/user/
β”‚
β”œβ”€β”€ laravel-core-deps/                # Folder global untuk dependency inti
β”‚   β”œβ”€β”€ vendor/                       # Hasil composer install (shared)
β”‚   β”œβ”€β”€ composer.json                 # Berisi laravel/framework dan package umum
β”‚   └── composer.lock
β”‚
β”œβ”€β”€ projectA/
β”‚   β”œβ”€β”€ vendor/
β”‚   β”‚   β”œβ”€β”€ laravel/                  # Symlink ke core
β”‚   β”‚   β”œβ”€β”€ guzzlehttp/              # Symlink ke core
β”‚   β”‚   β”œβ”€β”€ fruitcake/               # Symlink ke core
β”‚   β”‚   β”œβ”€β”€ barryvdh/laravel-dompdf  # Dependency spesifik Project A
β”‚   β”‚   └── autoload.php             # Symlink ke core
β”‚   β”œβ”€β”€ composer.json                # Berisi package tambahan Project A
β”‚   └── ...
β”‚
β”œβ”€β”€ projectB/
β”‚   β”œβ”€β”€ vendor/
β”‚   β”‚   β”œβ”€β”€ laravel/                  # Symlink ke core
β”‚   β”‚   β”œβ”€β”€ guzzlehttp/              # Symlink ke core
β”‚   β”‚   β”œβ”€β”€ maatwebsite/excel        # Dependency spesifik Project B
β”‚   β”‚   └── autoload.php             # Symlink ke core
β”‚   β”œβ”€β”€ composer.json
β”‚   └── ...
β”‚
└── projectC/
    β”œβ”€β”€ vendor/
    β”‚   β”œβ”€β”€ laravel/                  # Symlink ke core
    β”‚   β”œβ”€β”€ spatie/laravel-permission# Dependency spesifik Project C
    β”‚   └── autoload.php             # Symlink ke core
    β”œβ”€β”€ composer.json
    └── ...

🧩 Penjelasan Struktur

  • laravel-core-deps/: Menyimpan semua dependency yang dibutuhkan bersama oleh semua proyek. Composer hanya dijalankan sekali di sini.
  • projectA, projectB, projectC: Tetap memiliki folder vendor/, tapi isinya campuran antara symlink ke core dan folder asli untuk dependency tambahan.
  • autoload.php: Tetap tersedia di setiap proyek, bisa disymlink atau dibuat ulang agar autoload tetap berfungsi.

Integrasi Composer dari Proyek Lokal

Banyak proyek Laravel dikembangkan secara lokal dengan struktur standar: semua dependency disimpan di folder vendor/, dan composer.json mencakup seluruh packageβ€”baik core maupun spesifik. Saat berpindah ke sistem shared dependencies, kita perlu menyesuaikan agar composer install tetap bisa digunakan tanpa merusak symlink ke folder core.

🧩 Tantangan Migrasi

  • Composer akan mencoba meng-install semua dependency ke vendor/ lokal.
  • Jika vendor/ sudah berisi symlink ke folder core, Composer bisa:
    • Menghapus symlink dan menimpa dengan folder baru.
    • Gagal install karena konflik file/folder.
  • Tujuan kita: tetap bisa pakai composer install di proyek, tapi dependency inti tetap diarahkan ke shared folder.

βœ… Strategi Modular: Split Dependency dan Symlink

1. Pisahkan Dependency Core dan Spesifik

Buat dua file:

  • composer.core.json β†’ berisi dependency inti (Laravel, Guzzle, dsb.)
  • composer.json β†’ berisi dependency tambahan yang unik untuk proyek

Contoh composer.core.json:

{
  "require": {
    "laravel/framework": "^10.0",
    "guzzlehttp/guzzle": "^7.0",
    "fruitcake/laravel-cors": "^2.0"
  }
}
JSON

Contoh composer.json proyek:

{
  "require": {
    "barryvdh/laravel-dompdf": "^2.0",
    "spatie/laravel-permission": "^5.0"
  }
}
JSON

2. Install Core di Folder Global

Di folder ~/laravel-core-deps/, jalankan:

composer install --no-dev --no-scripts --no-autoloader
Bash

Ini akan meng-install dependency inti tanpa autoload yang bentrok.

3. Symlink Vendor Core ke Proyek

Di proyek Laravel:

rm -rf vendor
mkdir vendor
ln -s ~/laravel-core-deps/vendor/laravel vendor/laravel
ln -s ~/laravel-core-deps/vendor/guzzlehttp vendor/guzzlehttp
ln -s ~/laravel-core-deps/vendor/fruitcake vendor/fruitcake
ln -s ~/laravel-core-deps/vendor/autoload.php vendor/autoload.php
Bash

4. Install Dependency Spesifik di Proyek

Sekarang kamu bisa jalankan:

composer install
Bash

Composer akan membaca composer.json proyek dan hanya meng-install package tambahan ke vendor/, tanpa menyentuh symlink yang sudah ada.

🧠 Alternatif: Composer Path Repository (Advanced)

Untuk kasus tertentu, kamu bisa menggunakan path repository agar Composer mengambil package dari folder luar. Ini cocok untuk package custom, tapi tidak disarankan untuk Laravel core.

πŸ“Œ Tips Migrasi Aman

  • Backup composer.lock sebelum split.
  • Validasi autoload dengan php artisan setelah install.
  • Gunakan composer dump-autoload jika autoload bermasalah.

Dengan pendekatan ini, kamu bisa tetap menggunakan Composer seperti biasa, tanpa mengorbankan efisiensi inode dan modularitas proyek. Selanjutnya, kita akan bahas beberapa tips tambahan dan automasi untuk mempermudah pengelolaan banyak proyek Laravel.

Penutup

Mengelola banyak proyek Laravel di satu server bukan hanya soal efisiensi waktu, tapi juga efisiensi sumber daya. Dengan pendekatan layered dependency sharing, kita bisa menghemat ribuan inode, menjaga konsistensi antar proyek, dan tetap fleksibel untuk kebutuhan spesifik masing-masing aplikasi.

Strategi ini bukan sekadar trik teknis, tapi bagian dari filosofi pengembangan yang modular dan maintainableβ€”sesuatu yang semakin penting di era deployment cepat dan tim yang terdistribusi. Dengan memisahkan dependency inti dan spesifik, serta memanfaatkan symlink dan automasi, kita bisa membangun sistem yang scalable dan hemat biaya.

Share the Post:

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *