Electron - Panduan Cepat
Mengapa Electron?
Electron memungkinkan Anda membuat aplikasi desktop dengan JavaScript murni dengan menyediakan runtime dengan API asli (sistem operasi) yang kaya.
Ini tidak berarti Electron adalah pengikatan JavaScript ke pustaka antarmuka pengguna grafis (GUI). Sebaliknya, Electron menggunakan halaman web sebagai GUI-nya, jadi Anda juga dapat melihatnya sebagai browser Chromium minimal, yang dikontrol oleh JavaScript. Jadi semua aplikasi elektron secara teknis adalah halaman web yang berjalan di browser yang dapat memanfaatkan API OS Anda.
Siapa yang Menggunakan Elektron?
Github mengembangkan Electron untuk membuat editor teks Atom. Keduanya bersumber terbuka pada tahun 2014. Electron digunakan oleh banyak perusahaan seperti Microsoft, Github, Slack, dll.
Elektron telah digunakan untuk membuat sejumlah aplikasi. Berikut adalah beberapa aplikasi penting -
- Desktop kendur
- Aplikasi desktop Wordpress
- Kode Visual Studio
- Editor Penurunan Harga Caret
- Aplikasi Nylas Email
- Klien git GitKraken
Untuk mulai mengembangkan menggunakan Electron, Anda perlu menginstal Node dan npm (node package manager). Jika Anda belum memilikinya, buka Pengaturan node untuk menginstal node di sistem lokal Anda. Konfirmasikan bahwa node dan npm diinstal dengan menjalankan perintah berikut di terminal Anda.
node --version
npm --version
Perintah di atas akan menghasilkan output berikut -
v6.9.1
3.10.8
Setiap kali kita membuat proyek menggunakan npm, kita perlu menyediakan file package.jsonfile, yang memiliki semua detail tentang proyek kami. npm memudahkan kami menyiapkan file ini. Mari kita siapkan proyek pengembangan kita.
Jalankan terminal / cmd Anda, buat folder baru bernama hello-world dan buka folder itu menggunakan perintah cd.
Sekarang untuk membuat file package.json menggunakan npm, gunakan perintah berikut.
npm init
Ini akan meminta Anda untuk informasi berikut -
Terus tekan Enter, dan masukkan nama Anda di kolom "nama penulis".
Buat folder baru dan buka menggunakan perintah cd. Sekarang jalankan perintah berikut untuk menginstal Electron secara global.
$ npm install -g electron-prebuilt
Setelah dijalankan, Anda dapat memeriksa apakah Electron diinstal dengan cara yang benar dengan menjalankan perintah berikut -
$ electron --version
Anda harus mendapatkan hasilnya -
v1.4.13
Sekarang kita telah menyiapkan Electron, mari kita lanjutkan untuk membuat aplikasi pertama kita menggunakannya.
Electron mengambil file utama yang ditentukan dalam file package.json Anda dan menjalankannya. File utama ini membuat jendela aplikasi yang berisi halaman web yang dirender dan interaksi dengan GUI asli (antarmuka pengguna grafis) dari Sistem Operasi Anda.
Saat Anda memulai aplikasi menggunakan Electron, a main processdibuat. Proses utama ini bertanggung jawab untuk berinteraksi dengan GUI asli dari Sistem Operasi. Ini menciptakan GUI aplikasi Anda.
Hanya memulai proses utama tidak akan memberi pengguna aplikasi Anda jendela aplikasi apa pun. Ini dibuat oleh proses utama di file utama dengan menggunakan modul BrowserWindow . Setiap jendela browser kemudian berjalan sendiri-sendirirenderer process. Proses renderer mengambil file HTML yang mereferensikan file CSS biasa, file JavaScript, gambar, dll. Dan merendernya di jendela.
Proses utama dapat mengakses GUI asli melalui modul yang tersedia langsung di Electron. Aplikasi desktop dapat mengakses semua modul Node seperti modul sistem file untuk menangani file, permintaan untuk melakukan panggilan HTTP, dll.
Perbedaan antara proses Utama dan Renderer
Proses utama membuat halaman web dengan membuat instance BrowserWindow . Setiap instance BrowserWindow menjalankan halaman web dalam proses perendernya sendiri. Saat instance BrowserWindow dihancurkan, proses renderer terkait juga dihentikan.
Proses utama mengelola semua halaman web dan proses penyaji yang sesuai. Setiap proses perender diisolasi dan hanya peduli dengan halaman web yang berjalan di dalamnya.
Kami telah membuat package.jsonmengajukan untuk proyek kami. Sekarang kita akan membuat aplikasi desktop pertama kita menggunakan Electron.
Buat file baru yang disebut main.js . Masukkan kode berikut di dalamnya -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Buat file lain, kali ini file HTML bernama index.html . Masukkan kode berikut di dalamnya.
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
Jalankan aplikasi ini menggunakan perintah berikut -
$ electron ./main.js
Jendela baru akan terbuka. Ini akan terlihat seperti berikut -
Bagaimana Aplikasi Ini Bekerja?
Kami membuat file utama dan file HTML. File utama menggunakan dua modul - app dan BrowserWindow . Modul aplikasi digunakan untuk mengontrol siklus hidup kejadian aplikasi Anda sementara modul BrowserWindow digunakan untuk membuat dan mengontrol jendela browser.
Kami mendefinisikan fungsi createWindow , di mana kami membuat BrowserWindow baru dan melampirkan URL ke BrowserWindow ini. Ini adalah file HTML yang di-render dan ditampilkan kepada kami saat kami menjalankan aplikasi.
Kami telah menggunakan proses objek Electron asli di file html kami. Objek ini diperluas dari objek proses Node.js dan mencakup semuat=its fungsi sambil menambahkan lebih banyak lagi.
Antarmuka Pengguna aplikasi Electron dibangun menggunakan HTML, CSS dan JS. Jadi kami juga dapat memanfaatkan semua alat yang tersedia untuk pengembangan web front-end di sini. Anda dapat menggunakan alat seperti Angular, Backbone, React, Bootstrap, dan Foundation, untuk membuat aplikasi.
Anda dapat menggunakan Bower untuk mengelola dependensi front-end ini. Instal bower menggunakan -
$ npm install -g bower
Sekarang Anda bisa mendapatkan semua kerangka kerja JS dan CSS yang tersedia, pustaka, plugin, dll. Menggunakan bower. Misalnya, untuk mendapatkan versi stabil terbaru dari bootstrap, masukkan perintah berikut -
$ bower install bootstrap
Ini akan mengunduh bootstrap di bower_components . Sekarang Anda dapat mereferensikan pustaka ini di HTML Anda. Mari kita buat halaman sederhana menggunakan pustaka ini.
Sekarang mari kita instal jquery menggunakan perintah npm -
$ npm install --save jquery
Selanjutnya, ini akan diperlukan dalam file view.js kami. Kami sudah memiliki pengaturan main.js sebagai berikut -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Bukalah index.html file dan masukkan kode berikut di dalamnya -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
<link rel = "stylesheet"
href = "./bower_components/bootstrap/dist/css/bootstrap.min.css" />
</head>
<body>
<div class = "container">
<h1>This page is using Bootstrap and jQuery!</h1>
<h3 id = "click-counter"></h3>
<button class = "btn btn-success" id = "countbtn">Click here</button>
<script src = "./view.js" ></script>
</div>
</body>
</html>
Membuat view.js dan masukkan logika penghitung klik di dalamnya -
let $ = require('jquery') // jQuery now loaded and assigned to $
let count = 0
$('#click-counter').text(count.toString())
$('#countbtn').on('click', () => {
count ++
$('#click-counter').text(count)
})
Jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Perintah di atas akan menghasilkan output seperti pada gambar berikut -
Anda dapat membangun aplikasi asli Anda seperti Anda membuat situs web. Jika Anda tidak ingin pengguna dibatasi dengan ukuran jendela yang tepat, Anda dapat memanfaatkan desain responsif dan mengizinkan pengguna untuk menggunakan aplikasi Anda dengan cara yang fleksibel.
Penanganan file adalah bagian yang sangat penting dalam membangun aplikasi desktop. Hampir semua aplikasi desktop berinteraksi dengan file.
Kami akan membuat formulir di aplikasi kami yang akan mengambil masukan, Nama dan alamat Email. Formulir ini akan disimpan ke file dan daftar akan dibuat yang akan menampilkan ini sebagai output.
Siapkan proses utama Anda menggunakan kode berikut di main.js file -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Sekarang buka index.html file dan masukkan kode berikut di dalamnya -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File System</title>
<link rel = "stylesheet"
href = "./bower_components/bootstrap/dist/css/bootstrap.min.css" />
<style type = "text/css">
#contact-list {
height: 150px;
overflow-y: auto;
}
</style>
</head>
<body>
<div class = "container">
<h1>Enter Names and Email addresses of your contacts</h1>
<div class = "form-group">
<label for = "Name">Name</label>
<input type = "text" name = "Name" value = "" id = "Name"
placeholder = "Name" class = "form-control" required>
</div>
<div class = "form-group">
<label for = "Email">Email</label>
<input type = "email" name = "Email" value = "" id = "Email"
placeholder = "Email" class = "form-control" required>
</div>
<div class = "form-group">
<button class = "btn btn-primary" id = "add-to-list">Add to list!</button>
</div>
<div id = "contact-list">
<table class = "table-striped" id = "contact-table">
<tr>
<th class = "col-xs-2">S. No.</th>
<th class = "col-xs-4">Name</th>
<th class = "col-xs-6">Email</th>
</tr>
</table>
</div>
<script src = "./view.js" ></script>
</div>
</body>
</html>
Sekarang kita perlu menangani event penjumlahan. Kami akan melakukan ini di kamiview.js mengajukan.
Kami akan membuat fungsi loadAndDisplayContacts () yang awalnya akan memuat kontak dari file. Setelah membuat fungsi loadAndDisplayContacts () , kita akan membuat handler klik di fileadd to listtombol. Ini akan menambahkan entri ke file dan tabel.
Di file view.js Anda, masukkan kode berikut -
let $ = require('jquery')
let fs = require('fs')
let filename = 'contacts'
let sno = 0
$('#add-to-list').on('click', () => {
let name = $('#Name').val()
let email = $('#Email').val()
fs.appendFile('contacts', name + ',' + email + '\n')
addEntry(name, email)
})
function addEntry(name, email) {
if(name && email) {
sno++
let updateString = '<tr><td>'+ sno + '</td><td>'+ name +'</td><td>'
+ email +'</td></tr>'
$('#contact-table').append(updateString)
}
}
function loadAndDisplayContacts() {
//Check if file exists
if(fs.existsSync(filename)) {
let data = fs.readFileSync(filename, 'utf8').split('\n')
data.forEach((contact, index) => {
let [ name, email ] = contact.split(',')
addEntry(name, email)
})
} else {
console.log("File Doesn\'t Exist. Creating new file.")
fs.writeFile(filename, '', (err) => {
if(err)
console.log(err)
})
}
}
loadAndDisplayContacts()
Sekarang jalankan aplikasi, dengan menggunakan perintah berikut -
$ electron ./main.js
Setelah Anda menambahkan beberapa kontak ke dalamnya, aplikasi akan terlihat seperti -
Untuk lebih fs module API calls, silakan merujuk ke tutorial Sistem File Node .
Sekarang kita bisa menangani file menggunakan Electron. Kita akan melihat bagaimana memanggil kotak dialog simpan dan buka (asli) untuk file di bab dialog.
Kami menggunakan modul node, fs, di bab sebelumnya. Sekarang kita akan melihat beberapa modul node lain yang dapat kita gunakan dengan Electron.
Modul OS
Dengan menggunakan modul OS, kita bisa mendapatkan banyak informasi tentang sistem yang menjalankan aplikasi kita. Berikut adalah beberapa metode yang membantu saat aplikasi dibuat. Metode ini membantu kami menyesuaikan aplikasi sesuai dengan OS yang mereka jalankan.
Sr Tidak | Deskripsi fungsi |
---|---|
1 | os.userInfo([options]) Itu os.userInfo()metode mengembalikan informasi tentang pengguna yang saat ini efektif. Informasi ini dapat digunakan untuk mempersonalisasi aplikasi bagi pengguna bahkan tanpa meminta informasi secara eksplisit. |
2 | os.platform() Itu os.platform()metode mengembalikan string yang mengidentifikasi platform sistem operasi. Ini dapat digunakan untuk menyesuaikan aplikasi sesuai dengan OS pengguna. |
3 | os.homedir() Itu os.homedir()metode mengembalikan direktori home dari pengguna saat ini sebagai string. Umumnya, konfigurasi semua pengguna berada di direktori home pengguna. Jadi ini bisa digunakan untuk tujuan yang sama untuk aplikasi kita. |
4 | os.arch() Itu os.arch()metode mengembalikan string yang mengidentifikasi arsitektur CPU sistem operasi. Ini bisa digunakan saat menjalankan arsitektur eksotis untuk menyesuaikan aplikasi Anda dengan sistem itu. |
5 | os.EOL Konstanta string yang mendefinisikan penanda akhir baris khusus sistem operasi. Ini harus digunakan setiap kali mengakhiri baris dalam file di OS host. |
Menggunakan file main.js yang sama dan file HTML berikut, kita dapat mencetak properti ini di layar -
<html>
<head>
<title>OS Module</title>
</head>
<body>
<script>
let os = require('os')
document.write('User Info: ' + JSON.stringify(os.userInfo()) + '<br>' +
'Platform: ' + os.platform() + '<br>' +
'User home directory: ' + os.homedir() + '<br>' +
'OS Architecture: ' + os.arch() + '<br>')
</script>
</body>
</html>
Sekarang jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Perintah di atas akan menghasilkan output berikut -
User Info: {"uid":1000,"gid":1000,"username":"ayushgp","homedir":"/home/ayushgp",
"shell":"/usr/bin/zsh"}
Platform: linux
User home directory: /home/ayushgp
OS Architecture: x64
Modul Bersih
Modul net digunakan untuk pekerjaan terkait jaringan di aplikasi. Kita dapat membuat server dan koneksi soket menggunakan modul ini. Secara umum, penggunaan modul pembungkus dari npm direkomendasikan daripada penggunaan modul net untuk tugas-tugas terkait jaringan.
Tabel berikut mencantumkan metode yang paling berguna dari modul -
Sr Tidak | Deskripsi fungsi |
---|---|
1 | net.createServer([options][, connectionListener]) Membuat server TCP baru. Argumen connectionListener secara otomatis disetel sebagai pendengar untuk peristiwa 'koneksi'. |
2 | net.createConnection(options[, connectionListener]) Metode pabrik, yang mengembalikan 'net.Socket' baru dan menghubungkan ke alamat dan port yang disediakan. |
3 | net.Server.listen(port[, host][, backlog][, callback]) Mulailah menerima koneksi pada port dan host yang ditentukan. Jika host dihilangkan, server akan menerima koneksi yang diarahkan ke alamat IPv4 mana pun. |
4 | net.Server.close([callback]) Akhirnya ditutup ketika semua koneksi diakhiri dan server mengeluarkan acara 'tutup'. |
5 | net.Socket.connect(port[, host][, connectListener]) Membuka koneksi untuk soket yang diberikan. Jika port dan host diberikan, maka socket akan dibuka sebagai socket TCP. |
Modul net juga dilengkapi dengan beberapa metode lain. Untuk mendapatkan daftar yang lebih lengkap, lihat ini .
Sekarang, mari kita buat aplikasi elektron yang menggunakan modul net untuk membuat koneksi ke server. Kami perlu membuat file baru,server.js -
var net = require('net');
var server = net.createServer(function(connection) {
console.log('Client Connected');
connection.on('end', function() {
console.log('client disconnected');
});
connection.write('Hello World!\r\n');
connection.pipe(connection);
});
server.listen(8080, function() {
console.log('Server running on http://localhost:8080');
});
Menggunakan file main.js yang sama, ganti file HTML dengan yang berikut -
<html>
<head>
<title>net Module</title>
</head>
<body>
<script>
var net = require('net');
var client = net.connect({port: 8080}, function() {
console.log('Connection established!');
});
client.on('data', function(data) {
document.write(data.toString());
client.end();
});
client.on('end', function() {
console.log('Disconnected :(');
});
</script>
</body>
</html>
Jalankan server menggunakan perintah berikut -
$ node server.js
Jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Perintah di atas akan menghasilkan output berikut -
Perhatikan bahwa kami terhubung ke server secara otomatis dan secara otomatis terputus juga.
Kami juga memiliki beberapa modul node lain yang dapat digunakan langsung di front-end menggunakan Electron. Penggunaan modul ini bergantung pada skenario tempat Anda menggunakannya.
Electron memberi kita 2 modul IPC (Inter Process Communication) yang disebut ipcMain dan ipcRenderer.
Itu ipcMainmodul digunakan untuk berkomunikasi secara asinkron dari proses utama ke proses penyaji. Saat digunakan dalam proses utama, modul menangani pesan asinkron dan sinkron yang dikirim dari proses perender (halaman web). Pesan yang dikirim dari perender akan dikirim ke modul ini.
Itu ipcRenderermodul digunakan untuk berkomunikasi secara asinkron dari proses renderer ke proses utama. Ini menyediakan beberapa metode sehingga Anda dapat mengirim pesan sinkron dan asinkron dari proses perender (halaman web) ke proses utama. Anda juga dapat menerima balasan dari proses utama.
Kami akan membuat proses utama dan proses renderer yang akan saling mengirim pesan menggunakan modul di atas.
Buat file baru bernama main_process.js dengan konten berikut -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
// Event handler for asynchronous incoming messages
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg)
// Event emitter for sending asynchronous messages
event.sender.send('asynchronous-reply', 'async pong')
})
// Event handler for synchronous incoming messages
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
// Synchronous event emmision
event.returnValue = 'sync pong'
})
app.on('ready', createWindow)
Sekarang buat yang baru index.html file dan tambahkan kode berikut di dalamnya.
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
</head>
<body>
<script>
const {ipcRenderer} = require('electron')
// Synchronous message emmiter and handler
console.log(ipcRenderer.sendSync('synchronous-message', 'sync ping'))
// Async message handler
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg)
})
// Async message sender
ipcRenderer.send('asynchronous-message', 'async ping')
</script>
</body>
</html>
Jalankan aplikasi menggunakan perintah berikut -
$ electron ./main_process.js
Perintah di atas akan menghasilkan output berikut -
// On your app console
Sync Pong
Async Pong
// On your terminal where you ran the app
Sync Ping
Async Ping
Direkomendasikan untuk tidak melakukan komputasi tugas berat / pemblokiran pada proses perender. Selalu gunakan IPC untuk mendelegasikan tugas ini ke proses utama. Ini membantu dalam menjaga kecepatan aplikasi Anda.
Sangat penting bagi aplikasi apa pun untuk menjadi yang ramah pengguna. Akibatnya, Anda tidak boleh membuat kotak dialog menggunakan panggilan alert (). Electron menyediakan antarmuka yang cukup bagus untuk menyelesaikan tugas membuat kotak dialog. Mari kita lihat.
Elektron menyediakan a dialog modul yang dapat kita gunakan untuk menampilkan dialog sistem asli untuk membuka dan menyimpan file, memberi peringatan, dll.
Mari kita langsung beralih ke contoh dan membuat aplikasi untuk menampilkan file tekstil sederhana.
Buat file main.js baru dan masukkan kode berikut di dalamnya -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
ipcMain.on('openFile', (event, path) => {
const {dialog} = require('electron')
const fs = require('fs')
dialog.showOpenDialog(function (fileNames) {
// fileNames is an array that contains all the selected
if(fileNames === undefined) {
console.log("No file selected");
} else {
readFile(fileNames[0]);
}
});
function readFile(filepath) {
fs.readFile(filepath, 'utf-8', (err, data) => {
if(err){
alert("An error ocurred reading the file :" + err.message)
return
}
// handle the file content
event.sender.send('fileData', data)
})
}
})
app.on('ready', createWindow)
Kode ini akan membuka kotak dialog terbuka setiap kali proses utama kami menerima pesan 'openFile' dari proses renderer. Pesan ini akan mengarahkan kembali konten file ke proses renderer. Sekarang, kita harus mencetak isinya.
Sekarang, buat file index.html file dengan konten berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File read using system dialogs</title>
</head>
<body>
<script type = "text/javascript">
const {ipcRenderer} = require('electron')
ipcRenderer.send('openFile', () => {
console.log("Event sent.");
})
ipcRenderer.on('fileData', (event, data) => {
document.write(data)
})
</script>
</body>
</html>
Sekarang setiap kali kami menjalankan aplikasi kami, kotak dialog terbuka asli akan muncul seperti yang ditunjukkan pada gambar berikut -
Setelah kami memilih file untuk ditampilkan, isinya akan ditampilkan di jendela aplikasi -
Ini hanyalah salah satu dari empat dialog yang disediakan oleh Electron. Mereka semua memiliki penggunaan yang serupa. Setelah Anda mempelajari cara melakukannya dengan menggunakanshowOpenDialog, lalu Anda dapat menggunakan dialog lainnya.
Dialog yang memiliki fungsi yang sama adalah -
- showSaveDialog ([browserWindow,] options [, callback])
- showMessageDialog ([browserWindow,] options [, callback])
- showErrorDialog (judul, konten)
Aplikasi desktop hadir dengan dua jenis menu - application menu(di bilah atas) dan a context menu(menu klik kanan). Kita akan mempelajari cara membuat keduanya di bab ini.
Kami akan menggunakan dua modul - modul Menu dan MenuItem . Perhatikan bahwa modul Menu dan MenuItem hanya tersedia dalam proses utama. Untuk menggunakan modul ini dalam proses perender, Anda memerlukan modul jarak jauh . Kami akan menemukan ini ketika kami membuat menu konteks.
Sekarang, mari kita buat yang baru main.js file untuk proses utama -
const {app, BrowserWindow, Menu, MenuItem} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
const template = [
{
label: 'Edit',
submenu: [
{
role: 'undo'
},
{
role: 'redo'
},
{
type: 'separator'
},
{
role: 'cut'
},
{
role: 'copy'
},
{
role: 'paste'
}
]
},
{
label: 'View',
submenu: [
{
role: 'reload'
},
{
role: 'toggledevtools'
},
{
type: 'separator'
},
{
role: 'resetzoom'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
}
]
},
{
role: 'window',
submenu: [
{
role: 'minimize'
},
{
role: 'close'
}
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More'
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
app.on('ready', createWindow)
Kami sedang membangun menu dari template di sini. Ini berarti kami menyediakan menu sebagai JSON untuk fungsi tersebut dan itu akan mengurus sisanya. Sekarang kita harus mengatur menu ini sebagai menu Aplikasi.
Sekarang buat file HTML kosong bernama index.html dan jalankan aplikasi ini menggunakan -
$ electron ./main.js
Pada posisi normal menu aplikasi, Anda akan melihat menu berdasarkan template di atas.
Kami membuat menu ini dari proses utama. Mari kita sekarang membuat menu konteks untuk aplikasi kita. Kami akan melakukan ini di file HTML kami -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<script type = "text/javascript">
const {remote} = require('electron')
const {Menu, MenuItem} = remote
const menu = new Menu()
// Build menu one item at a time, unlike
menu.append(new MenuItem ({
label: 'MenuItem1',
click() {
console.log('item 1 clicked')
}
}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))
menu.append(new MenuItem ({
label: 'MenuItem3',
click() {
console.log('item 3 clicked')
}
}))
// Prevent default action of right click in chromium. Replace with our menu.
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
}, false)
</script>
</body>
</html>
Kami mengimpor modul Menu dan MenuItem menggunakan modul jarak jauh; kemudian, kami membuat menu dan menambahkan menuitems kami ke sana satu per satu. Selanjutnya, kami mencegah tindakan default klik kanan di chromium dan menggantinya dengan menu kami.
Pembuatan menu di Electron adalah tugas yang sangat sederhana. Sekarang Anda dapat melampirkan penangan acara Anda ke item ini dan menangani acara sesuai dengan kebutuhan Anda.
Baki sistem adalah menu di luar jendela aplikasi Anda. Di MacOS dan Ubuntu, ini terletak di sudut kanan atas layar Anda. Di Windows, tombol ini berada di pojok kanan bawah. Kita dapat membuat menu untuk aplikasi kita di system tray menggunakan Electron.
Buat yang baru main.jsfile dan tambahkan kode berikut ke dalamnya. Siapkan file png untuk digunakan untuk ikon baki sistem.
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Setelah menyiapkan jendela browser dasar, kami akan membuat yang baru index.html file dengan konten berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<script type = "text/javascript">
const {remote} = require('electron')
const {Tray, Menu} = remote
const path = require('path')
let trayIcon = new Tray(path.join('','/home/ayushgp/Desktop/images.png'))
const trayMenuTemplate = [
{
label: 'Empty Application',
enabled: false
},
{
label: 'Settings',
click: function () {
console.log("Clicked on settings")
}
},
{
label: 'Help',
click: function () {
console.log("Clicked on Help")
}
}
]
let trayMenu = Menu.buildFromTemplate(trayMenuTemplate)
trayIcon.setContextMenu(trayMenu)
</script>
</body>
</html>
Kami membuat baki menggunakan submodul Baki. Kami kemudian membuat menu menggunakan templat dan selanjutnya melampirkan menu ke objek baki kami.
Jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Saat Anda menjalankan perintah di atas, periksa baki sistem Anda untuk ikon yang Anda gunakan. Saya menggunakan wajah tersenyum untuk lamaran saya. Perintah di atas akan menghasilkan output berikut -
Electron menyediakan API notifikasi asli hanya untuk MacOS. Jadi kita tidak akan menggunakannya, sebaliknya kita akan menggunakan modul npm yang disebut node-notifier . Ini memungkinkan kami memberi tahu pengguna di Windows, MacOS, dan Linux.
Instal modul node-notifier di folder aplikasi Anda menggunakan perintah berikut di folder itu -
$ npm install --save node-notifier
Sekarang mari kita buat aplikasi yang memiliki tombol yang akan menghasilkan pemberitahuan setiap kali kita mengklik tombol ini.
Buat yang baru main.js file dan masukkan kode berikut di dalamnya -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Sekarang mari kita buat halaman web dan skrip yang akan memicu notifikasi. Buat yang baruindex.html file dengan kode berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<button type = "button" id = "notify" name = "button">
Click here to trigger a notification!</button>
<script type = "text/javascript">
const notifier = require('node-notifier')
const path = require('path');
document.getElementById('notify').onclick = (event) => {
notifier.notify ({
title: 'My awesome title',
message: 'Hello from electron, Mr. User!',
icon: path.join('','/home/ayushgp/Desktop/images.png'), // Absolute path
(doesn't work on balloons)
sound: true, // Only Notification Center or Windows Toasters
wait: true // Wait with callback, until user action is taken
against notification
}, function (err, response) {
// Response is response from notification
});
notifier.on('click', function (notifierObject, options) {
console.log("You clicked on the notification")
});
notifier.on('timeout', function (notifierObject, options) {
console.log("Notification timed out!")
});
}
</script>
</body>
</html>
Itu notify metode memungkinkan kita untuk menyebarkannya objectwithinformasi seperti judul, pesan, gambar kecil, dll. yang membantu kami menyesuaikan pemberitahuan. Kami juga dapat mengatur beberapa pendengar acara di notifikasi.
Sekarang, jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Ketika Anda mengklik tombol yang kami buat, Anda akan melihat pemberitahuan asli dari sistem operasi Anda seperti yang ditunjukkan pada gambar berikut -
Kami juga telah menangani peristiwa di mana, pengguna mengklik pemberitahuan atau waktu pemberitahuan habis. Metode ini membantu kami membuat aplikasi lebih interaktif jika berjalan di latar belakang.
Tag tampilan web digunakan untuk menyematkan konten 'tamu' seperti halaman web di aplikasi Electron Anda. Konten ini terkandung dalam wadah tampilan web. Halaman tersemat dalam aplikasi Anda mengontrol bagaimana konten ini akan ditampilkan.
Tampilan web berjalan dalam proses yang terpisah dari aplikasi Anda. Untuk memastikan keamanan dari konten berbahaya, tampilan web tidak memiliki izin yang sama seperti halaman web Anda. Ini membuat aplikasi Anda aman dari konten yang disematkan. Semua interaksi antara aplikasi Anda dan halaman tersemat akan menjadi asinkron.
Mari kita pertimbangkan contoh untuk memahami penyematan halaman web eksternal di aplikasi Electron kita. Kami akan menyematkan situs web tutorialspoint di aplikasi kami di sisi kanan. Buat yang barumain.js file dengan konten berikut -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Sekarang kita telah menyiapkan proses utama kita, mari kita buat file HTML yang akan menyematkan situs web tutorialspoint. Buat file bernama index.html dengan konten berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<div>
<div>
<h2>We have the website embedded below!</h2>
</div>
<webview id = "foo" src = "https://www.tutorialspoint.com/" style =
"width:400px; height:480px;">
<div class = "indicator"></div>
</webview>
</div>
<script type = "text/javascript">
// Event handlers for loading events.
// Use these to handle loading screens, transitions, etc
onload = () => {
const webview = document.getElementById('foo')
const indicator = document.querySelector('.indicator')
const loadstart = () => {
indicator.innerText = 'loading...'
}
const loadstop = () => {
indicator.innerText = ''
}
webview.addEventListener('did-start-loading', loadstart)
webview.addEventListener('did-stop-loading', loadstop)
}
</script>
</body>
</html>
Jalankan aplikasi menggunakan perintah berikut -
$ electron ./main.js
Perintah di atas akan menghasilkan output berikut -
Tag tampilan web juga dapat digunakan untuk sumber daya lain. Elemen tampilan web memiliki daftar kejadian yang dipancarkannya yang terdaftar di dokumen resmi. Anda dapat menggunakan peristiwa ini untuk meningkatkan fungsionalitas bergantung pada hal-hal yang terjadi di tampilan web.
Setiap kali Anda menyematkan skrip atau sumber daya lain dari Internet, disarankan untuk menggunakan tampilan web. Ini disarankan karena dilengkapi dengan manfaat keamanan yang besar dan tidak menghalangi perilaku normal.
Pengambilan audio dan video adalah karakteristik penting jika Anda membuat aplikasi untuk berbagi layar, memo suara, dll. Fitur tersebut juga berguna jika Anda memerlukan aplikasi untuk mengambil gambar profil.
Kami akan menggunakan API getUserMedia HTML5 untuk menangkap aliran audio dan video dengan Electron. Mari kita atur proses utama kita dimain.js mengajukan sebagai berikut -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
// Set the path where recordings will be saved
app.setPath("userData", __dirname + "/saved_recordings")
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Sekarang kita telah menyiapkan proses utama kita, mari kita buat file HTML yang akan menangkap konten ini. Buat file bernamaindex.html dengan konten berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Audio and Video</title>
</head>
<body>
<video autoplay></video>
<script type = "text/javascript">
function errorCallback(e) {
console.log('Error', e)
}
navigator.getUserMedia({video: true, audio: true}, (localMediaStream) => {
var video = document.querySelector('video')
video.src = window.URL.createObjectURL(localMediaStream)
video.onloadedmetadata = (e) => {
// Ready to go. Do some stuff.
};
}, errorCallback)
</script>
</body>
</html>
Program di atas akan menghasilkan keluaran sebagai berikut -
Anda sekarang memiliki streaming dari webcam dan mikrofon Anda. Anda dapat mengirim streaming ini melalui jaringan atau menyimpannya dalam format yang Anda suka.
Lihat Dokumentasi MDN untuk mengambil gambar untuk mendapatkan gambar dari webcam Anda dan menyimpannya. Ini dilakukan menggunakan API getUserMedia HTML5 . Anda juga dapat menangkap desktop pengguna menggunakan modul desktopCapturer yang disertakan dengan Electron. Sekarang mari kita lihat contoh bagaimana mendapatkan aliran layar.
Gunakan file main.js yang sama seperti di atas dan edit file index.html agar memiliki konten berikut -
desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => {
if (error) throw error
for (let i = 0; i < sources.length; ++i) {
if (sources[i].name === 'Your Window Name here!') {
navigator.webkitGetUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sources[i].id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
}, handleStream, handleError)
return
}
}
})
function handleStream (stream) {
document.querySelector('video').src = URL.createObjectURL(stream)
}
function handleError (e) {
console.log(e)
}
Kami telah menggunakan modul desktopCapturer untuk mendapatkan informasi tentang setiap jendela yang terbuka. Sekarang Anda dapat merekam kejadian dari aplikasi tertentu atau seluruh layar tergantung pada nama yang Anda berikan di atasif statement. Ini hanya akan mengalirkan apa yang terjadi di layar itu ke aplikasi Anda.
Anda dapat merujuk ke pertanyaan StackOverflow ini untuk memahami penggunaan secara detail.
Kami biasanya mengingat pintasan tertentu untuk semua aplikasi yang kami gunakan di PC setiap hari. Untuk membuat aplikasi Anda terasa intuitif dan mudah diakses oleh pengguna, Anda harus mengizinkan pengguna untuk menggunakan pintasan.
Kami akan menggunakan modul globalShortcut untuk menentukan pintasan di aplikasi kami. Catat ituAcceleratorsadalah String yang dapat berisi beberapa pengubah dan kode kunci, dikombinasikan dengan karakter +. Akselerator ini digunakan untuk menentukan pintasan keyboard di seluruh aplikasi kita.
Mari kita perhatikan contoh dan buat jalan pintas. Untuk ini, kami akan mengikuti contoh kotak dialog tempat kami menggunakan kotak dialog terbuka untuk membuka file. Kami akan mendaftarkanCommandOrControl+O pintasan untuk memunculkan kotak dialog.
Kami main.jskode akan tetap sama seperti sebelumnya. Jadi buat yang barumain.js file dan masukkan kode berikut di dalamnya -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
ipcMain.on('openFile', (event, path) => {
const {dialog} = require('electron')
const fs = require('fs')
dialog.showOpenDialog(function (fileNames) {
// fileNames is an array that contains all the selected
if(fileNames === undefined)
console.log("No file selected")
else
readFile(fileNames[0])
})
function readFile(filepath){
fs.readFile(filepath, 'utf-8', (err, data) => {
if(err){
alert("An error ocurred reading the file :" + err.message)
return
}
// handle the file content
event.sender.send('fileData', data)
})
}
})
app.on('ready', createWindow)
Kode ini akan membuka kotak dialog terbuka setiap kali proses utama kami menerima pesan 'openFile' dari proses renderer. Sebelumnya kotak dialog ini muncul setiap kali aplikasi dijalankan. Sekarang mari kita batasi untuk membuka hanya ketika kita menekanCommandOrControl+O.
Sekarang buat yang baru index.html file dengan konten berikut -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File read using system dialogs</title>
</head>
<body>
<p>Press CTRL/CMD + O to open a file. </p>
<script type = "text/javascript">
const {ipcRenderer, remote} = require('electron')
const {globalShortcut} = remote
globalShortcut.register('CommandOrControl+O', () => {
ipcRenderer.send('openFile', () => {
console.log("Event sent.");
})
ipcRenderer.on('fileData', (event, data) => {
document.write(data)
})
})
</script>
</body>
</html>
Kami mendaftarkan pintasan baru dan memberikan panggilan balik yang akan dijalankan setiap kali kami menekan pintasan ini. Kami dapat membatalkan pendaftaran pintasan jika dan saat kami tidak membutuhkannya.
Sekarang setelah aplikasi dibuka, kita akan mendapatkan pesan untuk membuka file menggunakan pintasan yang baru saja kita tentukan.
Pintasan ini dapat disesuaikan dengan memungkinkan pengguna memilih pintasannya sendiri untuk tindakan yang ditentukan.
Variabel Lingkungan mengontrol konfigurasi dan perilaku aplikasi tanpa mengubah kode. Perilaku Electron tertentu dikontrol oleh variabel lingkungan karena mereka diinisialisasi lebih awal dari tanda baris perintah dan kode aplikasi.
Ada dua jenis variabel lingkungan yang dikodekan dalam elektron - Production variables dan Development variables.
Variabel Produksi
Variabel lingkungan berikut ditujukan untuk digunakan saat runtime dalam aplikasi Electron yang dikemas.
Sr Tidak | Variabel & Deskripsi |
---|---|
1 | GOOGLE_API_KEY Electron menyertakan kunci API hardcode untuk membuat permintaan ke layanan web geocoding Google. Karena kunci API ini disertakan dalam setiap versi Electron, seringkali melebihi kuota penggunaannya. Untuk mengatasi ini, Anda dapat menyediakan kunci Google API Anda sendiri di lingkungan. Tempatkan kode berikut di file proses utama Anda, sebelum membuka jendela browser apa pun yang akan membuat permintaan geocoding - |
2 | ELECTRON_RUN_AS_NODE Memulai proses sebagai proses Node.js normal. |
3 | ELECTRON_FORCE_WINDOW_MENU_BAR (Linux Only) Jangan gunakan bilah menu global di Linux. |
Variabel Pengembangan
Variabel lingkungan berikut ditujukan terutama untuk tujuan pengembangan dan debugging.
Sr Tidak | Variabel & Deskripsi |
---|---|
1 | ELECTRON_ENABLE_LOGGING Mencetak logging internal Chrome ke konsol. |
2 | ELECTRON_ENABLE_STACK_DUMPING Mencetak jejak tumpukan ke konsol saat Electron mogok. |
3 | ELECTRON_DEFAULT_ERROR_MODE Menampilkan dialog macet Windows saat Elektron macet. |
Untuk menyetel salah satu dari variabel lingkungan ini sebagai true, setel di konsol Anda. Misalnya, jika Anda ingin mengaktifkan logging, gunakan perintah berikut -
Untuk Windows
> set ELECTRON_ENABLE_LOGGING=true
Untuk Linux
$ export ELECTRON_ENABLE_LOGGING=true
Perhatikan bahwa Anda perlu menyetel variabel lingkungan ini setiap kali Anda memulai ulang komputer. Jika Anda ingin menghindarinya, tambahkan baris ini ke file.bashrc file.
Kami memiliki dua proses yang menjalankan aplikasi kami - proses utama dan proses renderer.
Karena proses perender adalah yang sedang dijalankan di jendela browser kita, kita dapat menggunakan Chrome Devtools untuk men-debugnya. Untuk membuka DevTools, gunakan pintasan "Ctrl + Shift + I" atau tombol <F12>. Anda dapat melihat cara menggunakan devtools di sini .
Saat Anda membuka DevTools, aplikasi Anda akan terlihat seperti yang ditunjukkan pada tangkapan layar berikut -
Debugging Proses Utama
DevTools di jendela browser Electron hanya dapat men-debug JavaScript yang dijalankan di jendela itu (yaitu, halaman web). Untuk men-debug JavaScript yang dijalankan dalam proses utama, Anda perlu menggunakan debugger eksternal dan meluncurkan Electron dengan sakelar --debug atau --debug-brk .
Electron akan mendengarkan pesan protokol debugger V8 pada port yang ditentukan; debugger eksternal perlu terhubung ke port ini. Port default adalah 5858.
Jalankan aplikasi Anda menggunakan berikut ini -
$ electron --debug = 5858 ./main.js
Sekarang Anda memerlukan debugger yang mendukung protokol debugger V8. Anda dapat menggunakan VSCode atau node-inspector untuk tujuan ini. Misalnya, mari kita ikuti langkah-langkah ini dan menyiapkan VSCode untuk tujuan ini. Ikuti langkah-langkah berikut untuk menyiapkannya -
Unduh dan instal VSCode . Buka proyek Electron Anda di VSCode.
Tambahkan file .vscode/launch.json dengan konfigurasi berikut -
{
"version": "1.0.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"program": "${workspaceRoot}/main.js"
}
]
}
Note - Untuk Windows, gunakan "${workspaceRoot}/node_modules/.bin/electron.cmd" untuk runtimeExecutable.
Tetapkan beberapa breakpoint main.js, dan mulai debugging dalam Debug View. Saat Anda mencapai breakpoint, layar akan terlihat seperti ini -
Debugger VSCode sangat kuat dan akan membantu Anda memperbaiki kesalahan dengan cepat. Anda juga memiliki opsi lain sepertinode-inspector untuk men-debug aplikasi elektron.
Mengemas dan mendistribusikan aplikasi merupakan bagian integral dari proses pengembangan aplikasi desktop. Karena Electron adalah kerangka kerja pengembangan aplikasi desktop lintas platform, pengemasan dan distribusi aplikasi untuk semua platform juga harus menjadi pengalaman yang mulus.
Komunitas elektron telah menciptakan sebuah proyek, pengemas elektron yang menangani hal yang sama untuk kita. Ini memungkinkan kami untuk mengemas dan mendistribusikan aplikasi Electron kami dengan bundel khusus OS (.app, .exe dll) melalui JS atau CLI.
Platform yang Didukung
Electron Packager berjalan pada platform host berikut -
- Windows (32/64 bit)
- OS X
- Linux (x86 / x86_64)
Ini menghasilkan executable / bundel untuk platform target berikut -
- Windows (juga dikenal sebagai win32, untuk 32/64 bit)
- OS X (juga dikenal sebagai darwin) / Mac App Store (juga dikenal sebagai mas)
- Linux (untuk arsitektur x86, x86_64, dan armv7l)
Instalasi
Pasang pengemas elektron menggunakan -
# for use in npm scripts
$ npm install electron-packager --save-dev
# for use from cli
$ npm install electron-packager -g
Aplikasi Pengemasan
Di bagian ini, kita akan melihat bagaimana menjalankan pengemas dari baris perintah. Bentuk dasar dari perintah tersebut adalah -
electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]
Ini akan -
Temukan atau unduh rilis Electron yang benar.
Gunakan versi Electron itu untuk membuat aplikasi di <output-folder> / <appname> - <platform> - <arch>.
--platform dan --archdapat dihilangkan, dalam dua kasus. Jika Anda menentukan--allsebaliknya, bundel untuk semua kombinasi yang valid dari platform / arsitektur target akan dibuat. Jika tidak, satu bundel untuk platform / arsitektur host akan dibuat.
Kami telah menggunakan sumber daya berikut untuk mempelajari lebih lanjut tentang Elektron. Kami telah merujuk ini saat membuat tutorial ini.
Sumber daya yang paling penting adalah dokumentasi Electron. Dokumentasi memiliki cakupan yang luas dari hampir semua fitur dan kebiasaan kerangka kerja. Mereka sendirian cukup untuk membuat jalan Anda melalui pembuatan aplikasi.
Ada juga beberapa contoh Elektron yang sangat bagus yang disajikan dalam penyimpanan aplikasi sampel elektron .
Sumber Video
Aplikasi desktop dengan bahasa web
Pengembangan aplikasi desktop lintas platform yang cepat menggunakan JavaScript dan Electron
Posting Blog
Membangun aplikasi desktop dengan Electron
Bangun Pemutar Musik dengan React & Electron
Membuat Aplikasi Desktop Pertama Anda Dengan HTML, JS, dan Elektron
Buat Aplikasi Node Desktop Lintas Platform dengan Electron