6 yıl önce 7 yorum
Merhaba, bildiğiniz üzere neredeyse web üzerinde yapılabilecek tüm programları masaüstü programı yapan electron projesi var. Bu konuda detaylı anlatım yapan bir makale bulamadığım için react, webpack, babel, electron kullanarak ve bunu paketleyerek bir örnek yapmak istedim. Umarım yararlı olur.
Başlangıç için kısa bir bilgi vermeliyim. Şimdi işletim sistemi ile client arasında veri paylaşımı yapmayı anlatacağım.
Bu konuda yine tercih ettiğim üzere kurulum dışında sadece bu konuyu anlatacağım. Electron kurulumu yapmak için diğer kaynaklardan faydalanabilirsiniz.
Electron’un en sevdiğim yönü bize nodejs’in işletim sisteminde yapabildiği özellikleri sunması. Biz de bu özellikleri ui üzerinde görebiliyoruz.
Tamam peki biz nodejs üzerinde yaptığımız işleri ui’da bulunan değişkenlerle nasıl kontrol ederiz. (yani veri paylaşımı nasıl yaparız)
Bu konuyu dokümanından bakarak bulabildim bkz. Burada native ile ui’ı haberleştirmek için iki fonksiyon kullanılıyor. Bunlar ipcMain ve ipcRenderer, isimlerinden de anlaşılacağı üzere ipcMain nodejs’in erişebildiği işlemleri yapıyor, ipcRenderer ise ipcMain’e haber vererek veya dinleyerek işlem yapıyor.
Basit bir örnek ile açıklayacak olursak:
// Main process içinde tanımlıyoruz.
const os = require('os');
const {ipcMain} = require('electron')
// burada ui'ı (renderer'ı) dinleyeceğiz
// eğer çağrılırsa anında değer döndüreceğiz
ipcMain.on('isletimSisteminiGetir', (event, arg) => {
event.returnValue = os.platform();
});
// UI içinde (yani aslında yazdığımız projenin içinde kullanımı)
const {ipcRenderer} = require('electron');
// burada sendSync ile anında değer gelmesi ve onu değişkene atmasını istiyoruz.
var sistem = ipcRenderer.sendSync('isletimSisteminiGetir')
alert('Bu bilgisayarın işletim sistemi:' + sistem);
Buraya kadar güzel görünüyor, fakat biz eğer gecikmeli bir işlem yapacaksak bunu şu şekilde yaparız:
// Main process tarafında
const os = require('os');
const {ipcMain} = require('electron')
ipcMain.on('isletimSisteminiGetirIstersen', (event, arg) => {
// bu şekilde uzun sürecek işlemleri tekrar yönlendirme yaparak giderebiliyoruz
event.sender.send('buyurIsletimSistemin', os.platform());
});
// aynı şekilde renderer (ui) tarafında
const {ipcRenderer} = require('electron');
ipcRenderer.on('buyurIsletimSistemin', (event, arg) => {
alert('Bu bilgisayarın işletim sistemi:' + arg));
})
// bu şekilde istersek bize veri dönmek zorunda olmadığı için hemen diğer satıra geçer
ipcRenderer.send('isletimSisteminiGetirIstersen');
Artık bunu da öğrendiğimize göre, Nodejs ile ne yapmak istiyorsak bunu ui üzerinde görüntüleyebiliriz demektir.
Bir örnek üzerinde hemen deneyelim.
Bir react projesi oluşturalım. Tüm ayarlarını kendimiz yapalım. Önce yeni bir klasör oluşturuyoruz.
mkdir sistem-ne
cd sistem-ne/
Hemen package.json dosyasını oluşturmak için npm init -f
komutunu çalıştırıyoruz. Uygulamamız için gerekli olan bağımlılıkları package.json dosyasında bulunan ‘dependencies’ içine bunları yazıyoruz:
{
"react": "^15.4.1",
"react-dom": "^15.4.1"
}
Geliştirme yapmak için ise devDependencies içine bunları yazıyoruz:
{
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"electron": "^1.7.6",
"html-webpack-plugin": "^2.26.0",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
}
Uygulamayı tarayıcı üzerinde test etmek için ise webpack-dev-server kullanacağız. Bunun için package.json dosyasına start script’ini ekliyoruz:
"scripts": {
"start": "webpack-dev-server"
}
Ardından .babelrc dosyasını touch .babelrc
ile oluşturuyoruz ve içine şu ayarları yazıyoruz:
{
"presets": ["es2015", "react"]
}
Şimdi 2 adet webpack ayarı kullanmamız gerekecek. İlk önce webpack.config.js dosyasını yazalım:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: './dist',
filename: 'index_bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ }
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body'
})
]
}
Sonra electron için çalıştırmamız gereken target: 'electron-renderer'
özelliğini kullanmak için electron.webpack.config.js dosyasını oluşturalım çünkü UI tarafında require('electron')
kullandığınız anda Error: Cannot resolve module ‘fs’ with electron and js hatası ile karşılaşırız. Çünkü biz bir browser uygulaması yapıyoruz ve doğal olarak dosya sistemine erişemiyoruz. Webpack’de target adında bir ayarlama var ve bu ayarlama ile uygulamayı neye göre derleyeceğini belirtiyoruz. webpack.config.js dosyasının aynısı fakat target özelliği ekliyoruz:
…
module.exports = {
target: 'electron-renderer',
…
}
Projemizde require(‘electron’) kullanmak için webpack’in bize sağladığı alias özelliğini kullanarak sanki electron varmış gibi davranmasını sağlayarak biraz önce bahsettiğim hatanın çıkmamasını sağlıyoruz. webpack.config.js dosyasına bir özellik daha ekliyoruz:
…
module.exports = {
resolve: {
alias: {
// electron alias'ı için herhangi bir yol göstermemiz gerekiyor
// biz ana dizine aliases.js adında boş bir dosya oluşturuyoruz
electron: __dirname + '/aliases.js'
}
},
…
}
Electron’u başlatmak için main.js dosyası ve (sadece electron üzerinde kullanılan bağımlılıkların olduğu) package.json dosyasına ihtiyacımız olacak o yüzden iki dosya oluşturmamız gerekiyor. İlk önce electron.package.json dosyasını oluşturalım:
{
"name": "sistem-ne",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {}
}
İkinci dosyamız ise electron.main.js dosyası (örneğin aynısı):
const electron = require('electron')
const app = electron.app
// Tarayıcı penceresi için gerekli
const BrowserWindow = electron.BrowserWindow
const path = require('path')
const url = require('url')
/* pencere için global bir referans oluşturuyoruz */
let mainWindow
function createWindow () {
// yeni tarayıcı penceresi.
mainWindow = new BrowserWindow({width: 800, height: 600})
// sonra index.html dosyasını uygulamaya ekliyoruz.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
// Başlangıçta geliştirme penceresini açabilirsiniz
// mainWindow.webContents.openDevTools()
// Pencere kapatıldığında
mainWindow.on('closed', function () {
// pencere bellekte yer kaplamaması için boşaltıyoruz.
mainWindow = null
})
}
// Electron'a ait herşeyin yüklenmesi bittiğinde çalışır
app.on('ready', createWindow)
// Tüm pencereler hapatıldığında
app.on('window-all-closed', function () {
// Eğer OSX değilse bu şekilde çıkabiliyor.
// OSX için sadece Cmd + Q ile çıkış yapılabilir.
if (process.platform !== 'darwin') {
app.quit()
}
})
// Uygulama penceresi her aktif olduğunda tetiklenir
app.on('activate', function () {
// Eğer window yoksa yeniden oluşturuyor
if (mainWindow === null) {
createWindow()
}
})
Şimdi bu dosyaları inşa etmek ve electron dosyalarını kopyalamak için işlemler yapalım. build, start:electron ve copy:electron script’lerini package.json dosyasına girmenin zamanı geldi:
{
"scripts": {
…,
"copy:electron": "cp electron.package.json ./dist/package.json && cp electron.main.js ./dist/main.js",
"build": "webpack .",
"start:electron": "webpack --config electron.webpack.config.js && npm run copy:electron && electron ./dist"
}
}
Uygulama, eğer npm run start:electron
komutunu çalıştırırsak başarılı bir şekilde çalışacak. Hatırladığınız üzere örneğe başlamadan önce bir bilgi vermiştik hemen onu deneyelim. İlk önce electron.main.js dosyasında işletim sisteminin bilgisini almamız için gerekli olan kodu yazalım:
…
/* pencere için global bir referans oluşturuyoruz */
let mainWindow
const os = require('os');
const {ipcMain} = require('electron')
// burada ui'ı (renderer'ı) dinleyeceğiz
// eğer çağrılırsa anında değer döndüreceğiz
ipcMain.on('isletimSisteminiGetir', (event, arg) => {
event.returnValue = os.platform();
});
function createWindow () {
…
Artık bunu yaptığımıza göre projemizde bulunan src/index.js dosyasında işletim sistemini alert ile gösterebiliriz:
var electron = require('electron');
if (electron.ipcRenderer) { // eğer bu kontrolü yapmazsak tarayıcı üzerinde Cannot read property 'sendSync' of undefined hatasını alırız
const ipcRenderer = electron.ipcRenderer;
// burada sendSync ile anında değer gelmesi ve onu değişkene atmasını istiyoruz.
var sistem = ipcRenderer.sendSync('isletimSisteminiGetir');
alert('Bu bilgisayarın işletim sistemi:' + sistem);
}
Ve npm run start:electron
komutunu çalıştırdığımızda şu görüntü ile karşılaşırız:
Fakat tarayıcı üzerinde bu işlem gerçekleşmeyecektir. Çünkü tarayıcı üzerinden (native erişimli) nodejs modülü çalıştıramayız.
Her işletim sistemi için ayrı paketleme yöntemi var. Tüm işletim sistemlerini paketleyebilecek bir proje var. Biz de onu kullanacağız. Yalnız eğer windows derlemesi yapmak istiyorsanız ve unix (benzeri OS) kullanıyorsanız bilgisayarınızda Winekurulu olması gerekir. electron-packager’i kurmak için şu komutu çalıştırıyoruz:
npm i electron-packager --save-dev
electron-packager paketleme işlemi yaparken, belirttiğiniz dizini temel alır. Yani eğer node_modules dosyası olmayan bir klasörü temel alırsanız main.js dosyasında belirttiğiniz bağımlılıklar çalışmayacaktır. Dikkat ederseniz yaptığımız projede build komutuyla herşeyi dist dizinine çıkarıyoruz. Yani bu dizinde node_modules yok! “Peki biz node_modules’i nasıl oraya taşırız. node_modules çok büyük” diyorsak şu görsele inanmalıyız :)
Bunun çözümü sembolink link eklemek olacaktır, yani dist dosyasına node_modules adında bir sembolink adres ekleyeceğiz. package.json dosyasına iki script daha ekleyelim:
{
"scripts": {
…,
"link:electron": "rm -rf ./dist/node_modules && ln -s ../node_modules ./dist",
"pack:electron": "webpack --config electron.webpack.config.js && npm run copy:electron && npm run link:electron && electron-packager ./dist"
}
}
Kısaca açıklayacak olursak link:electron
ile dist dizinine bir üst dizindeki node_modules klasörünü sembol alacak link ekliyoruz.
pack:electron
ile de uygulamayı webpack ile derledikten ve gerekli işlemleri yaptıktan sonra electron-packager ./dist
komutu ile uygulamayı paketliyoruz ve ana dizinde ‘sistem-ne-darwin-x64’ dosyasında paketlenmiş halini buluyoruz.
electron-packager’in dokümanını okuyarak diğer işlemleri kullanabilirsiniz. Şu an sadece bulunduğu işletim sistemine göre paketleme yapıyor. Siz –platform özelliğini kullanarak istediğiniz işletim sistemine derleyebilirsiniz.
Bu projeyi indirmek ve kurmak için:
git clone https://github.com/abdurrahmanekr/electron-react-example.git
cd electron-react-example
npm i
npm start
Aslında bu projede react ile ilgili bir işlem yapılmadı. Herhangi bir proje ile anlatmak isterdim fakat nasıl bir proje olacağı hakkında bir fikrim olmadığı için, olurda yarın projeye dönüştürme düşüncem olursa react uyumlu olsun diye react ile uyumlu yaptım. Okuduğunuz ve zaman ayırdığınız için teşekkürler :) (Proje fikriniz varsa yorumlarda belirtebilirsiniz.)
Bugün anlatacaklarım bu kadardı aklınıza takılan bir soru olursa çekinmeyin. Eğer bu konu hakkında veya konu dışı olarak bana soru sormak istiyorsanız https://github.com/abdurrahmanekr/bana-istedigini-sor repository’sinde bir issue açabilirsiniz. Youtube kanalıma abone olarak ve yayınladığım bu makaleyi paylaşarak bana destek olabilirsiniz. Diğer makalelerde görüşmek üzere :)
Düşündüklerin nedir ?
Yorumlar ({{totalCommentCount}})
{{commentLike42Count}} beğenme 6 yıl önce
{{commentLike43Count}} beğenme 6 yıl önce
{{commentLike56Count}} beğenme 6 yıl önce
{{commentLike57Count}} beğenme 6 yıl önce
{{commentLike58Count}} beğenme 6 yıl önce
{{commentLike59Count}} beğenme 6 yıl önce
{{commentLike91Count}} beğenme 5 yıl önce