Gerçek Örneklerle Electron IPC İletişimi Açıklaması
Electron, HTML, CSS ve JavaScript gibi web teknolojilerini kullanarak platformlar arası masaüstü uygulamaları geliştirmek için en popüler framework’lerden biridir. Arka planda Electron, Node.js çalıştıran bir Ana İşlem (Main Process) ve kullanıcı arayüzünü oluşturmak için Chromium çalıştıran bir veya daha fazla Oluşturucu İşlem (Renderer Process)‘den oluşan çoklu işlem mimarisine sahiptir.
Güvenlik riskleri nedeniyle, modern Electron uygulamaları Oluşturucu İşlemi işletim sisteminden izole eder. Bu, Oluşturucu arayüzünden doğrudan Node.js modüllerine veya sistem kaynaklarına (dosya okumak veya veritabanı sorgulamak gibi) erişemeyeceğiniz anlamına gelir.
Bu açığı güvenli bir şekilde kapatmak için Electron, İşlemler Arası İletişim (IPC) teknolojisini kullanır.
Bu kılavuzda Electron IPC’nin nasıl çalıştığını açıklayacak ve üretime hazır gerçek kod örnekleriyle üç temel iletişim modelini inceleyeceğiz.
1. Oluşturucudan Ana İşleme (Tek Yönlü / One-Way)
Bu model, Oluşturucu herhangi bir yanıt beklemeden Ana işleme bir komut veya eylem göndermek istediğinde kullanılır. Yaygın bir örnek, uygulama penceresini simge durumuna küçültmek veya kapatmak için arayüzdeki bir düğmeye tıklanmasıdır.
Bunun üç ana dosyada (main.js, preload.js ve renderer.js) nasıl uygulandığını görelim.
Ana İşlem (main.js)
Oluşturucu işleminden gelen olayları dinlemek için ipcMain.on kullanırız.
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
win.loadFile('index.html');
}
// Oluşturucudan 'close-app' olayını dinle
ipcMain.on('close-app', () => {
app.quit();
});
Önyükleme Betiği (preload.js)
Tüm ipcRenderer modülünü oluşturucuya sunmak yerine, contextBridge.exposeInMainWorld kullanarak oluşturucuya yalnızca güvenli bir sarmalayıcı işlev sunarız.
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
closeApp: () => ipcRenderer.send('close-app')
});
Oluşturucu İşlem (renderer.js)
window nesnesi üzerinde sunulan işlevi çağırırız.
const closeButton = document.getElementById('close-btn');
closeButton.addEventListener('click', () => {
window.electronAPI.closeApp();
});
2. Oluşturucudan Ana İşleme (Çift Yönlü / İstek-Yanıt)
Bu model, Oluşturucunun Ana işlemden veri talep etmesi veya bir sistem işlemini tetiklemesi ve sonucu beklemesi gerektiğinde kullanılır (örneğin dosya okumak veya güvenli bir veritabanı sorgusu yapmak).
Ana işlemde ipcMain.handle ve Önyükleme betiğinde ipcRenderer.invoke kullanırız.
Ana İşlem (main.js)
ipcMain.handle kullanarak isteği dinler ve verileri asenkron olarak döndürürüz.
const { ipcMain } = require('electron');
const fs = require('fs/promises');
// 'read-file' çağrısını asenkron olarak yönet
ipcMain.handle('read-file', async (event, filePath) => {
try {
const data = await fs.readFile(filePath, 'utf-8');
return { success: true, content: data };
} catch (error) {
return { success: false, error: error.message };
}
});
Önyükleme Betiği (preload.js)
Bir Promise döndüren asenkron bir sarmalayıcı sunarız.
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath)
});
Oluşturucu İşlem (renderer.js)
Döndürülen Promise’in çözümlenmesini beklemek için await kullanırız.
const readBtn = document.getElementById('read-btn');
readBtn.addEventListener('click', async () => {
const result = await window.electronAPI.readFile('/path/to/file.txt');
if (result.success) {
console.log('Dosya İçeriği:', result.content);
} else {
console.error('Dosya okunamadı:', result.error);
}
});
3. Ana İşlemden Oluşturucuya (Tek Yönlü Bildirim)
Bu model, Ana işlemin Oluşturucu işleme güncellemeler veya bildirimler göndermesi gerektiğinde kullanılır (örneğin indirme ilerleme çubuğu güncellemeleri, uygulama menüsü tıklamaları veya arka plan hizmeti durum güncellemeleri).
Ana işlemde webContents.send ve Önyükleme betiğinde ipcRenderer.on kullanırız.
Ana İşlem (main.js)
Etkin pencerenin webContents nesnesini alır ve mesajı göndeririz.
// Örnek: İndirme ilerleme durumunu gönderme
function trackDownloadProgress(mainWindow) {
let progress = 0;
const interval = setInterval(() => {
progress += 10;
mainWindow.webContents.send('download-progress', progress);
if (progress >= 100) {
clearInterval(interval);
}
}, 1000);
}
Önyükleme Betiği (preload.js)
Geri çağırma işlevi alan bir abonelik yöntemi sunarız. Bellek sızıntılarını önlemek için bir temizleme (dinleyiciyi kaldırma) işlevi döndürmek iyi bir uygulamadır.
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
onDownloadProgress: (callback) => {
const subscription = (event, value) => callback(value);
ipcRenderer.on('download-progress', subscription);
// Bellek sızıntısını önlemek için temizleme işlevini döndür
return () => {
ipcRenderer.removeListener('download-progress', subscription);
};
}
});
Oluşturucu İşlem (renderer.js)
Olaylara abone olun ve arayüzü güncelleyin.
const progressBar = document.getElementById('progress-bar');
const unsubscribe = window.electronAPI.onDownloadProgress((progress) => {
progressBar.style.width = `${progress}%`;
progressBar.textContent = `${progress}%`;
if (progress === 100) {
console.log('İndirme tamamlandı!');
unsubscribe(); // Bellek sızıntısını önlemek için dinleyiciyi temizle
}
});
4. Güvenlik En İyi Pratikleri
Electron IPC ile çalışırken güvenlik birinci önceliğiniz olmalıdır. IPC güvenli değilse Oluşturucu işleme sızan kötü amaçlı kodlar tüm işletim sistemini tehlikeye atabilir.
Şu hayati kurallara uyun:
ipcRendererNesnesini Asla Doğrudan Sunmayın:contextBridge.exposeInMainWorld('electron', ipcRenderer)yazmayın. Bunu yapmak, oluşturucunun herhangi bir IPC mesajı göndermesine tam erişim sağlayarak güvenlik sınırlarını ortadan kaldırır.- Bağlam Yalıtımını (Context Isolation) Etkin Tutun:
webPreferencesayarlarında her zamancontextIsolation: truevenodeIntegration: falseolarak ayarlayın. - Girdileri Doğrulayın: Ana işlemde alınan bağımsız değişkenleri (dosya yolları veya veritabanı sorguları gibi) çalıştırmadan önce her zaman doğrulayın.
ipcMain.on+webContents.sendYerineipcMain.handleTercih Edin: İstek-yanıt modelleri içininvoke/handlekullanımı daha temizdir, Promise yapılarını yerel olarak çözer ve birden fazla dinleyici geri çağırmasının karışmasını önler.
Sonuç
IPC iletişimini anlamak, güvenli, yüksek performanslı ve kararlı Electron uygulamaları oluşturmanın anahtarıdır. Doğru modeli kullanarak ve Bağlam Yalıtımını uygulayarak, kullanıcılarınızı güvende tutarken masaüstünde Node.js’in tüm gücünden yararlanabilirsiniz.