React ve Node.js Projelerinde Monorepo Kullanımı: Ölçeklenebilir Geliştirme İçin Modern Yaklaşım

Modern yazılım geliştirme pratiklerinde, projelerin karmaşıklığı ve ekip büyüklükleri arttıkça, kod tabanlarını yönetmek de giderek zorlaşıyor. Birçok geliştirici, her mikroservis veya frontend uygulaması için ayrı bir Git deposu (polyrepo) kullanma eğilimindedir. Ancak benim geliştirme tecrübelerimde, özellikle birbirine bağlı React frontend ve Node.js backend projeleri üzerinde çalışırken, bu "çoklu depo" yaklaşımının bazı noktalarda yönetimi zorlaştırdığını ve verimliliği düşürdüğünü gözlemledim. İşte tam bu noktada, Monorepo yaklaşımı güçlü bir alternatif olarak devreye giriyor.
Bu yazıda, React ve Node.js projeleriniz için monorepo yapısının ne olduğunu, neden bu yaklaşımı tercih etmeniz gerektiğini, kurulum adımlarını ve yaygın olarak kullanılan araçları detaylı bir şekilde inceleyeceğiz. Amacımız, tek bir Git deposu içinde birden fazla projenizi daha organize, ölçeklenebilir ve bakımı kolay bir şekilde yönetmenizi sağlayacak pratik bilgiler sunmak.
Monorepo Nedir? Polyrepo'dan Farkı
Monorepo (tekli depo), birden fazla projenin veya paketin aynı Git deposu içinde barındırıldığı bir yazılım geliştirme stratejisidir. Bu projeler tamamen bağımsız uygulamalar, paylaşılan kütüphaneler veya farklı mikroservisler olabilir. Öte yandan, polyrepo (çoklu depo) yaklaşımında ise her projenin veya mikroservisin kendine ait ayrı bir Git deposu bulunur.
Monorepo, sanılanın aksine tek bir devasa proje demek değildir; daha ziyade, ilişkili projelerin mantıksal olarak ayrık ama fiziksel olarak birleşik bir yapıda olmasını ifade eder. Google, Meta (eski adıyla Facebook), Microsoft gibi büyük teknoloji şirketleri, yıllardır bu yaklaşımı başarıyla kullanmaktadır.
Neden Monorepo Kullanmalıyız? Avantajları ve Faydaları
React ve Node.js gibi birbirini tamamlayan teknolojilerle geliştirme yaparken monorepo'nun sunduğu avantajlar göz ardı edilemez:
- Kod Paylaşımı ve Yeniden Kullanılabilirlik: Frontend (React) ve backend (Node.js) arasında veya farklı React uygulamaları arasında ortak tipleri, doğrulama şemalarını, yardımcı fonksiyonları veya UI bileşenlerini kolayca paylaşabilirsiniz. Örneğin, API sözleşmelerinizi tanımlayan bir TypeScript arayüzü, hem Node.js API'nizde hem de React istemcinizde tek bir yerden yönetilebilir. Hatırlarsanız, React'te İleri Seviye Bileşen Desenleri yazımda da kod tekrarını önlemenin önemine değinmiştim.
- Tutarlı Geliştirme Ortamı: Tüm projeleriniz aynı kodlama standartları, linting kuralları ve test yapılandırmaları ile yönetilebilir. Bu, geliştiriciler arasında tutarlılığı artırır ve yeni ekip üyelerinin projeye adaptasyonunu kolaylaştırır.
- Basitleştirilmiş Bağımlılık Yönetimi: Projeler arası bağımlılıklar (örneğin, bir React uygulaması tarafından kullanılan paylaşılan bir bileşen kütüphanesi) çok daha kolay yönetilir. Lokal bağımlılıkları yayımlamak veya sembolik bağlar (symlink) oluşturmakla uğraşmanıza gerek kalmaz.
- Atomik Değişiklikler: Bir özellik geliştirirken, bu özelliğin hem frontend hem de backend kısımlarını tek bir Git commit'i ile değiştirebilirsiniz. Bu, değişikliklerin senkronizasyonunu ve dağıtımını kolaylaştırır. Özellikle mikroservis mimarilerinde (Node.js ile Ölçeklenebilir Mikroservisler yazımda bahsettiğim gibi), atomik commit'ler, ilgili servislerin aynı anda güncellenmesi gerektiğinde büyük kolaylık sağlar.
- Tekli CI/CD Pipeline'ları: Tek bir depo, genellikle tüm projeler için ortak veya koşullu tetiklenen CI/CD pipeline'ları oluşturmanıza olanak tanır. Bu da altyapı yönetimini basitleştirir.
- Büyük Resme Hakimiyet: Geliştiriciler, tüm sistemin nasıl çalıştığına dair daha iyi bir genel bakışa sahip olur, bu da daha bilinçli mimari kararlar almalarına yardımcı olur.
Monorepo'nun Zorlukları ve Nasıl Üstesinden Gelinir?
Her mimari yaklaşımda olduğu gibi, monorepo'nun da kendi zorlukları vardır:
- Öğrenme Eğrisi ve Araç Seçimi: Monorepo'ları yönetmek için Lerna, Nx, Turborepo gibi özel araçlara ihtiyaç duyulur. Bu araçların öğrenilmesi ve doğru şekilde yapılandırılması başlangıçta zaman alabilir.
- Derleme ve Test Süreleri: Büyük monorepo'larda, tüm projeleri derlemek veya test etmek uzun sürebilir. Akıllı araçlar (Nx gibi) sadece değişen projeleri ve onlara bağımlı olanları test ederek bu sorunu azaltır.
- Depo Büyüklüğü: Zamanla depo boyutu artabilir, bu da `git clone` sürelerini uzatabilir. Ancak modern Git versiyonları ve araçları (Sparse Checkout gibi) bu sorunu yönetilebilir kılar.
- Erişim Kontrolü ve Güvenlik: Tüm kod tabanının tek bir yerde olması, erişim kontrolü stratejilerini daha kritik hale getirir. Tüm ekibin her şeye erişimi olması istenmeyebilir. Bu durum, organizasyonel politikalar ve Git sağlayıcınızın özellikleri ile yönetilebilir.

Monorepo Araçları: Lerna ve Nx
Monorepo'ları yönetmek için birçok araç mevcuttur. En popüler ikisi Lerna ve Nx'tir:
Lerna
Lerna, npm veya yarn kullanarak birden fazla JavaScript/TypeScript projesini (paketini) yönetmeye yardımcı olan bir araçtır. Özellikle paylaşılan kütüphaneler ve bağımsız dağıtılabilir paketler için idealdir. Komutları ile bağımlılıkları yönetebilir, tüm paketlerde script çalıştırabilir ve versiyonlama/yayınlama süreçlerini kolaylaştırır.
Nx (Nrwl Extensible)
Nx, bir üst seviye monorepo aracıdır. Sadece paket yönetimi değil, aynı zamanda kod üretimi (schematics), etkilenen dosyaların tespiti (affected commands), akıllı önbellekleme ve dağıtılmış görev yürütme gibi gelişmiş özellikler sunar. React, Angular, Node.js, Next.js gibi birçok framework ve teknolojiyle entegre olabilir. Büyük ölçekli ve çok teknolojili monorepo'lar için daha güçlü bir çözümdür.
Lerna ile Basit Bir React ve Node.js Monorepo Kurulumu
Şimdi Lerna kullanarak basit bir monorepo yapısı oluşturalım. Bu örnekte bir React frontend uygulaması, bir Node.js API'si ve bu iki proje arasında paylaşılan bir `utils` kütüphanesi olacak.
Adım 1: Monorepo Oluşturma
mkdir my-monorepo
cd my-monorepo
npm init -y
npm install lerna --save-dev
npx lerna initBu komutlar, `lerna.json` ve `packages` klasörünü oluşturacak.
Adım 2: Paketleri Oluşturma
Şimdi `packages` klasörü içinde projelerimizi oluşturalım:
# React uygulaması (frontend)
npx create-react-app packages/frontend --template typescript
# Node.js API (backend)
mkdir packages/backend
cd packages/backend
npm init -y
npm install express --save
touch index.js
# Paylaşılan Utilities (shared)
mkdir packages/shared
cd packages/shared
npm init -y
touch index.ts # TypeScript kullanıyoruz diyelimÖrnek `packages/backend/index.js` içeriği:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 4000;
app.get('/api/data', (req, res) => {
res.json({ message: 'Merhaba, Monorepo Backend!' });
});
app.listen(PORT, () => {
console.log(`Backend ${PORT} portunda çalışıyor.`);
});Örnek `packages/shared/index.ts` içeriği:
export const greet = (name: string): string => {
return `Merhaba, ${name}!`;
};
export interface ApiResponse {
message: string;
}Adım 3: Paketler Arası Bağımlılık Kurulumu
Şimdi `frontend` paketinin `shared` paketine bağımlılığını ekleyelim. Lerna ile bu çok kolaydır:
cd my-monorepo
npx lerna add shared packages/frontendBu komut, `packages/frontend/package.json` dosyasına `shared` paketini lokal bir bağımlılık olarak ekleyecektir. Şimdi `frontend` uygulamanızda `shared` paketini kullanabilirsiniz:
// packages/frontend/src/App.tsx
import React from 'react';
import { greet, ApiResponse } from 'shared'; // shared paketini import et
function App() {
const [message, setMessage] = React.useState('');
React.useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then((data: ApiResponse) => setMessage(data.message));
}, []);
return (
<div>
<h1>{greet('React Uygulaması')} </h1> {/* shared paketini kullan */}
<p>Backend Mesajı: {message}</p>
</div>
);
}
export default App;
Adım 4: Lerna Komutlarını Kullanma
Lerna, tüm paketlerde komut çalıştırmanıza olanak tanır:
- Tüm paketlerin bağımlılıklarını kurmak:
lerna bootstrap(Zatenlerna addsırasında bağımlılıklar kurulur.) - Tüm paketlerde `build` script'ini çalıştırmak:
lerna run build - Tüm paketlerde `test` script'ini çalıştırmak:
lerna run test
Özellikle `shared` paketi gibi TypeScript tabanlı kütüphaneler için `build` script'i önemlidir. `packages/shared/package.json` dosyanıza bir `build` script'i eklemeyi unutmayın (örneğin, `"build": "tsc"`).
Monorepo'da CI/CD ve Test Stratejileri
Monorepo'ların belki de en karmaşık görünen, ama doğru araçlarla en verimli hale getirilebilecek yönlerinden biri CI/CD ve test süreçleridir.
- Akıllı Testler: Nx gibi araçlar, sadece son commit'ten etkilenen projeleri test etmenize olanak tanır. Örneğin, sadece `backend` klasöründeki bir değişiklik olduğunda `backend` testlerini çalıştırır, `frontend` testlerini es geçer. Bu, CI pipeline'larının süresini önemli ölçüde kısaltır.
- Kademeli Dağıtım: Her paketin kendi dağıtım sürecine sahip olması mümkündür. Bir `backend` değişikliği sadece `backend` servisini yeniden dağıtırken, `frontend` değişikliği bir ön uç dağıtımını tetikleyebilir.
- Versiyonlama ve Yayımlama: Lerna, monorepo içindeki paketlerin versiyonlarını yönetmek ve bunları npm'e veya özel bir depoya yayımlamak için güçlü araçlar sunar (`lerna publish`).
Bu konularda daha derinlemesine bilgi almak için Node.js ve Express.js'te Güçlü Hata Yönetimi veya React Native Uygulamalarında Performans Optimizasyonu gibi yazılarımda bahsettiğim gibi, sürekli entegrasyon ve dağıtımın (CI/CD) bir projenin başarısı için ne kadar kritik olduğunu hatırlatmak isterim. Monorepo yapısı, bu süreçleri tek bir çatı altında daha tutarlı hale getirme potansiyeli taşır.

Sonuç
React ve Node.js projelerinde monorepo kullanımı, geliştirme sürecinizi dönüştürebilecek güçlü bir yaklaşımdır. Kod paylaşımını artırarak, bağımlılık yönetimini basitleştirerek ve takım içi işbirliğini güçlendirerek hem verimliliği hem de kod kalitesini önemli ölçüde artırabilir. Başlangıçta bir öğrenme eğrisi olsa da, Lerna veya Nx gibi doğru araçlarla bu zorlukların üstesinden gelmek mümkündür.
Eğer siz de projelerinizin büyümesiyle artan karmaşıklıktan şikayetçiyseniz veya birden fazla ilişkili projeyi daha entegre bir şekilde yönetmek istiyorsanız, monorepo yaklaşımına mutlaka bir şans vermelisiniz. Unutmayın, en iyi mimari, projenizin mevcut ve gelecekteki ihtiyaçlarına en iyi cevap veren mimaridir.
Eğer aklınıza takılan sorular olursa veya bu konularda daha derinlemesine bilgi almak isterseniz, bana ismailyagci371@gmail.com adresinden veya sosyal medya kanallarından benimle (İsmail YAĞCI) iletişime geçebilirsiniz. Sağlıklı ve başarılı kodlamalar dilerim!
Orijinal yazı: https://ismailyagci.com/articles/react-ve-nodejs-projelerinde-monorepo-kullanimi-olceklenebilir-gelistirme-icin-modern-yaklasim
Yorumlar
Yorum Gönder