Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!
[NODE JS] fs.watch ile Dosya Degisikligi Izleme
Merhaba arkadaslar, bugun sizinle Node.js'in belki de en az konusulan ama bir o kadar da ise yarayan ozelliklerinden biri olan fs.watch fonksiyonunu konusacagiz. Ben bunu ilk kez bir projede hot-reload mekanizmasi kurarken kesfettim ve o gundan beri bir cok farkli senaryoda kullandim. Ozellikle dosya degisikliklerini anlik olarak takip etmek istediginiz durumlarda inanilmaz pratik bir cozum sunuyor.
fs.watch Nedir ve Neden Kullanilir?
fs.watch, Node.js'in yerlesik fs modulunde bulunan ve dosya sistemindeki degisiklikleri izlemenizi saglayan bir fonksiyondur. Bir dosya veya klasor uzerinde degisiklik oldugunda sizi bilgilendiren bir watcher olusturur. Ben genelde bunu config dosyalarinin degisimini takip etmek, log dosyalarini canli izlemek veya gelistirme ortaminda otomatik yeniden yukleme yapmak icin kullaniyorum.
Isletim sistemi seviyesinde calisan bu fonksiyon, dosya sisteminin native event mekanizmasini kullanir. Yani surekli dosyayi okuyup kontrol etmez, isletim sistemi bir degisiklik oldugunda Node.js'e haber verir. Bu da performans acisindan buyuk bir avantaj saglar. Ha bu arada, buna "polling" yerine "event-driven" yaklasim deniyor.
Temel Kullanim
En basit haliyle fs.watch su sekilde calisir: bir dosya yolu verirsiniz, bir callback fonksiyonu tanimlarsiniz ve dosyada her degisiklik oldugunda bu callback tetiklenir. Callback fonksiyonu iki parametre alir: eventType ve filename. eventType ya "rename" ya da "change" olabilir. rename dosyanin adi degistiginde veya silindigi/olusturuldugu zaman, change ise icerik degistiginde tetiklenir.
JavaScript:
const fs = require('fs');
const path = require('path');
// Tek bir dosyayi izleme
const dosyaYolu = path.join(__dirname, 'config.json');
console.log('Dosya izleme baslatildi...');
console.log('Izlenen dosya:', dosyaYolu);
const watcher = fs.watch(dosyaYolu, (eventType, filename) => {
const simdi = new Date().toLocaleTimeString('tr-TR');
if (eventType === 'change') {
console.log(`[${simdi}] Dosya degisti: ${filename}`);
// Degisen dosyanin icerigini okuyalim
fs.readFile(dosyaYolu, 'utf8', (err, data) => {
if (err) {
console.error('Dosya okunamadi:', err.message);
return;
}
try {
const config = JSON.parse(data);
console.log('Yeni config degerleri:', config);
} catch (parseErr) {
console.error('JSON parse hatasi:', parseErr.message);
}
});
} else if (eventType === 'rename') {
console.log(`[${simdi}] Dosya yeniden adlandirildi veya silindi: ${filename}`);
}
});
watcher.on('error', (error) => {
console.error('Watcher hatasi:', error.message);
});
// Programi durdurmak icin
process.on('SIGINT', () => {
console.log('\nIzleme durduruluyor...');
watcher.close();
process.exit(0);
});
Klasor Izleme ve Recursive Secenegi
Benim en cok kullandigim senaryo aslinda tek bir dosya degil, bir klasorun tamamini izlemek. Mesela src klasorunuzdeki tum dosyalari izleyip degisiklik oldugunda bir build islemi baslatmak isteyebilirsiniz. Bunun icin recursive secenegini kullanabilirsiniz ama dikkat edin, bu secenek her platformda ayni sekilde calismayabiliyor. macOS ve Windows'ta sorunsuz calisir ama Linux'ta recursive destegi sinirlidir.
Tecrubeme gore Linux ortaminda recursive izleme yapacaksaniz, chokidar gibi bir kutuphane kullanmanizi tavsiye ederim. Ama Windows veya macOS'ta calisiyorsaniz native fs.watch gayet yeterli olacaktir.
JavaScript:
const fs = require('fs');
const path = require('path');
// Klasoru recursive olarak izleme
const klasorYolu = path.join(__dirname, 'src');
const watchOptions = {
recursive: true, // Alt klasorleri de izle
persistent: true, // Process'i ayakta tut
encoding: 'utf8' // Dosya adi encoding'i
};
console.log('Klasor izleme baslatildi:', klasorYolu);
const watcher = fs.watch(klasorYolu, watchOptions, (eventType, filename) => {
if (!filename) return; // Bazi sistemlerde filename null gelebilir
const tamYol = path.join(klasorYolu, filename);
const uzanti = path.extname(filename).toLowerCase();
// Sadece belirli dosya turlerini izle
const izlenecekUzantilar = ['.js', '.ts', '.json', '.css'];
if (!izlenecekUzantilar.includes(uzanti)) {
return; // Bu uzantiyi umursamiyoruz
}
console.log(`\n=== Degisiklik Algilandi ===`);
console.log(`Tur: ${eventType}`);
console.log(`Dosya: ${filename}`);
console.log(`Tam Yol: ${tamYol}`);
console.log(`Zaman: ${new Date().toLocaleString('tr-TR')}`);
// Dosya var mi kontrol et (rename event'inde silinmis olabilir)
fs.access(tamYol, fs.constants.F_OK, (err) => {
if (err) {
console.log('Dosya silindi veya tasindi.');
} else {
console.log('Dosya guncellendi.');
// Burada build, lint veya test calistirabilirsiniz
}
});
});
watcher.on('error', (err) => {
console.error('Izleme hatasi:', err);
});
console.log('Degisiklikleri izliyorum... (Ctrl+C ile durdurabilirsiniz)');
Debounce ile Tekrarlanan Event'leri Onleme
fs.watch ile calisirken karsilasacaginiz en buyuk sorunlardan biri, tek bir dosya kaydinda birden fazla event tetiklenmesidir. Bu isletim sistemi seviyesinde olan bir sey ve bunu engelleyemezsiniz. Ama debounce mekanizmasiyla bu sorunu kolayca cozebilirsiniz. Benim tavsiyem, 100-200ms'lik bir debounce suresi koymak. Bu sure icinde gelen tum event'leri tek bir event olarak degerlendirirsiniz.
Ben production ortaminda bu pattern'i kullanmadan once cok basim agridi. Bir dosya kaydedildiginde bazen 3-4 kez event geliyordu ve her seferinde build islemi baslatiliyordu. Debounce ekledikten sonra bu sorun tamamen ortadan kalkti.
JavaScript:
const fs = require('fs');
const path = require('path');
// Debounce mekanizmasi ile dosya izleme
class DosyaIzleyici {
constructor(hedefYol, options = {}) {
this.hedefYol = hedefYol;
this.debounceMs = options.debounceMs || 150;
this.zamanlayicilar = new Map();
this.watcher = null;
this.degisiklikSayaci = 0;
}
baslat() {
this.watcher = fs.watch(
this.hedefYol,
{ recursive: true },
(eventType, filename) => {
this._debounceHandler(eventType, filename);
}
);
this.watcher.on('error', (err) => {
console.error('Watcher hatasi:', err.message);
this.yenidenBaslat();
});
console.log(`Izleme baslatildi: ${this.hedefYol}`);
}
_debounceHandler(eventType, filename) {
if (!filename) return;
const anahtar = `${eventType}-${filename}`;
if (this.zamanlayicilar.has(anahtar)) {
clearTimeout(this.zamanlayicilar.get(anahtar));
}
const zamanlayici = setTimeout(() => {
this.zamanlayicilar.delete(anahtar);
this.degisiklikSayaci++;
this._degisiklikIsle(eventType, filename);
}, this.debounceMs);
this.zamanlayicilar.set(anahtar, zamanlayici);
}
_degisiklikIsle(eventType, filename) {
console.log(`[#${this.degisiklikSayaci}] ${eventType}: ${filename}`);
}
durdur() {
if (this.watcher) {
this.watcher.close();
this.zamanlayicilar.forEach(t => clearTimeout(t));
this.zamanlayicilar.clear();
console.log('Izleme durduruldu.');
}
}
yenidenBaslat() {
console.log('Izleme yeniden baslatiliyor...');
this.durdur();
setTimeout(() => this.baslat(), 1000);
}
}
// Kullanim
const izleyici = new DosyaIzleyici(path.join(__dirname, 'src'), {
debounceMs: 200
});
izleyici.baslat();
process.on('SIGINT', () => {
izleyici.durdur();
process.exit(0);
});
Dikkat Edilmesi Gerekenler
fs.watch kullanirken birkac onemli noktaya dikkat etmeniz gerekiyor. Birincisi, farkli isletim sistemlerinde farkli davranabilir. Linux'ta inotify, macOS'ta FSEvents ve Windows'ta ReadDirectoryChangesW kullaniyor. Bu yuzden cross-platform bir uygulama gelistiriyorsaniz, her platformda test etmeyi ihmal etmeyin.
Ikincisi, cok fazla dosya izlediginizde sistem kaynaklarini tuketebilirsiniz. Linux'ta varsayilan inotify limiti genelde 8192 civarindadir. Bunu asarsaniz ENOSPC hatasi alirsiniz. Bu durumda ya limiti artirmaniz ya da izlediginiz dosya sayisini azaltmaniz gerekir.
Son olarak, watcher'i kullanmayi bitirdiginizde mutlaka close() metoduyla kapatmayi unutmayin. Aksi takdirde memory leak olusabilir ve uygulamaniz zamanla yavaslar. Benim basima gelmisti, saatlerce neden memory leak oldugunu aradim, sonunda kapanmayan watcher'larin oldugunu fark ettim. O gunden beri watcher'lari her zaman try-finally blogu icinde kullaniyorum. Neyse, bu kadar. Bir sonraki konuda gorusuruz!
Emeğiniz ve katkınız için teşekkür ederiz!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 2
- Görüntüleme
- 390
- Cevaplar
- 1
- Görüntüleme
- 36
- Sabit
- Cevaplar
- 3
- Görüntüleme
- 384
- Cevaplar
- 1
- Görüntüleme
- 522
- Cevaplar
- 0
- Görüntüleme
- 408
