React Projelerde Feature-Based Klasör Yapısı: Modüler Organizasyon Rehberi
React projelerde feature-based klasör yapısı nasıl kurulur? Klasik vs modüler yapı karşılaştırması, barrel exports, shared bileşenler ve 15 modüllü...
Sorun: 100+ Dosya Nereye Koyulur?
Proje büyüdükçe components/Button.tsx, components/Table.tsx, components/Modal.tsx… 100 tane bileşen bir klasörde. Hangi modülün parçası? Nerede kullanılıyor? Bulmak imkansız.
Klasik vs Feature-Based Yapı
❌ Klasik (Tip Bazlı) Yapı
src/
├── components/
│ ├── Button.tsx ← 50+ bileşen burada
│ ├── OrderTable.tsx
│ ├── StockCard.tsx
│ └── CustomerModal.tsx
├── hooks/
│ ├── useOrders.ts
│ └── useStock.ts
├── services/
│ ├── orderService.ts
│ └── stockService.ts
└── pages/
├── Orders.tsx
└── Stock.tsx
Sorunlar:
OrderTablenerede kullanılıyor? → Aramak lazımuseOrdershangi bileşenle ilişkili? → Belli değil- Bir modülü silmek → dosyaları tek tek bulmak gerekiyor
✅ Feature-Based (Modüler) Yapı
src/
├── features/
│ ├── orders/
│ │ ├── components/
│ │ │ ├── OrderTable.tsx
│ │ │ ├── OrderStatusBadge.tsx
│ │ │ └── OrderFilters.tsx
│ │ ├── hooks/
│ │ │ └── useOrders.ts
│ │ ├── services/
│ │ │ └── orderApi.ts
│ │ ├── types.ts
│ │ └── index.ts ← barrel export
│ │
│ ├── stock/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── index.ts
│ │
│ └── customers/
│ ├── components/
│ ├── hooks/
│ └── index.ts
│
├── shared/
│ ├── components/ ← Button, Modal, Skeleton
│ ├── hooks/ ← useDebounce, useLocalStorage
│ └── utils/ ← formatCurrency, formatDate
│
├── lib/
│ └── supabase.ts ← SDK client'lar
│
└── app/
├── App.tsx
└── routes.tsx
Barrel Exports
Her feature klasöründe bir index.ts dosyası public API’yi tanımlar:
// features/orders/index.ts
export { OrderTable } from './components/OrderTable';
export { OrderStatusBadge } from './components/OrderStatusBadge';
export { useOrders } from './hooks/useOrders';
export type { Order, OrderStatus } from './types';
// Kullanım — temiz import
import { OrderTable, useOrders } from '@/features/orders';
// Yerine — kötü import
import { OrderTable } from '@/features/orders/components/OrderTable';
import { useOrders } from '@/features/orders/hooks/useOrders';
Shared vs Feature Bileşeni
Feature bileşeni: Sadece o modülde kullanılır, başka yerde anlamsız.
features/orders/components/OrderStatusBadge.tsx ← Sadece siparişte
Shared bileşen: 2+ modülde kullanılır, genel amaçlı.
shared/components/DataTable.tsx ← Her yerde tablo var
shared/components/StatusBadge.tsx ← Genel badge bileşeni
Kural: Bir bileşen 2. kez başka modülde kullanılacaksa → shared/’a taşıyın.
API Katmanı Organizasyonu
// features/orders/services/orderApi.ts
import { supabase } from '@/lib/supabase';
import type { Order } from '../types';
export const orderApi = {
async getAll(): Promise<Order[]> {
const { data, error } = await supabase
.from('orders')
.select('*')
.order('created_at', { ascending: false });
if (error) throw error;
return data;
},
async getById(id: string): Promise<Order> {
const { data, error } = await supabase
.from('orders')
.select('*')
.eq('id', id)
.single();
if (error) throw error;
return data;
},
async create(order: Omit<Order, 'id' | 'created_at'>): Promise<Order> {
const { data, error } = await supabase
.from('orders')
.insert(order)
.select()
.single();
if (error) throw error;
return data;
},
};
Ne Zaman Monorepo’ya Geçmeli?
| Durum | Feature-Based | Monorepo |
|---|---|---|
| Tek uygulama | ✅ | Gereksiz |
| 2+ uygulama shared code ile | ❌ | ✅ |
| Farklı deploy döngüleri | ❌ | ✅ |
| Farklı takımlar | ❌ | ✅ |
| Shared npm paketleri | ❌ | ✅ |
İlgili Yazılar
- React Modular Dashboard — Dashboard bileşen organizasyonu
- Multi-Tenant Mimari — Tenant bazlı feature organizasyonu
- React Cascading Filtreler — Feature bileşen örneği
Bu rehber Bulletproof React ve React Architecture Best Practices kaynağına dayanarak hazırlanmıştır.