type
Post
status
Published
date
Aug 19, 2025
slug
mengemas-aplikasi-nodejs-ke-installer-windows-exe-dengan-proteksi-kode-dan-kontrol-layanan
summary
Siap Ubah Aplikasi Node.js Server-Side Anda Menjadi Produk Windows Profesional?
Pelajari panduan langkah demi langkah tentang cara mengemas aplikasi Node.js TypeScript Anda menjadi satu file
.exe
yang mudah diinstal. Artikel ini akan menunjukkan cara melindungi kode sumber, mengonfigurasi aplikasi untuk berjalan sebagai layanan Windows yang tangguh di latar belakang, dan membuat GUI desktop intuitif untuk mengontrol layanan (Start/Stop/Restart) dan memantau log secara real-time. Hentikan interaksi manual di terminal dan berikan pengalaman profesional kepada pengguna Anda.tags
nodejs
express
javascript
typescript
category
article
password
icon
URL
Ringkasan Audio
Abstrak Eksekutif
Laporan ini menyajikan panduan komprehensif untuk mendistribusikan aplikasi Node.js TypeScript, yang memanfaatkan socket.io dan puppeteer, sebagai produk Windows yang mandiri dan terlindungi. Laporan ini membahas setiap langkah penting, mulai dari persiapan kode sumber, pengemasan aplikasi menjadi satu file executable (.exe), implementasi proteksi kode untuk menyembunyikan logika bisnis, hingga konfigurasi aplikasi agar berjalan sebagai layanan Windows di latar belakang. Selain itu, laporan ini memandu dalam pembuatan installer yang mudah digunakan dan pengembangan antarmuka pengguna grafis (GUI) yang intuitif untuk mengontrol layanan (memulai, menghentikan, me-restart) dan memantau log konsol secara real-time. Tujuannya adalah untuk memberdayakan pengembang Node.js agar dapat mengubah aplikasi server-side mereka menjadi solusi desktop yang siap didistribusikan secara komersial, memberikan pengalaman pengguna akhir yang mulus dan profesional.
Pendahuluan
Latar Belakang
Mendistribusikan aplikasi Node.js yang awalnya dirancang untuk lingkungan server sebagai produk desktop Windows menghadirkan serangkaian tantangan unik. Pengguna akhir mengharapkan pengalaman "aplikasi jadi" yang familiar, serupa dengan program .exe tradisional, lengkap dengan proses instalasi yang sederhana, kemampuan untuk berjalan di latar belakang, dan antarmuka kontrol yang intuitif. Hal ini sangat berbeda dengan alur kerja pengembangan Node.js yang umum, yang sering melibatkan perintah terminal seperti npm install dan npm run dev/start. Tantangan utama meliputi pengemasan runtime Node.js, proteksi kode sumber JavaScript yang biasanya terbuka, serta integrasi aplikasi sebagai layanan sistem Windows.
Tujuan Artikel
Artikel ini dirancang sebagai panduan teknis yang komprehensif dan langkah-demi-langkah untuk menjembatani kesenjangan antara pengembangan Node.js server-side dan distribusi aplikasi desktop Windows. Laporan ini membahas secara detail setiap komponen yang diperlukan untuk mengubah proyek Node.js TypeScript yang menggunakan socket.io dan puppeteer menjadi produk Windows yang dapat didistribusikan secara profesional, lengkap dengan proteksi kode dan GUI kontrol yang responsif.
Gambaran Umum Solusi
Solusi yang diusulkan dalam panduan ini dibangun di atas empat pilar utama yang saling terkait:
- Pengemasan Aplikasi: Proses mengubah seluruh kode sumber Node.js dan dependensinya menjadi satu file executable Windows (.exe) yang mandiri, menghilangkan kebutuhan akan instalasi Node.js terpisah di mesin pengguna.
- Proteksi Kode Sumber: Penerapan teknik obfuscation untuk menyembunyikan atau mempersulit pembacaan kode sumber JavaScript, melindungi kekayaan intelektual.
- Manajemen Layanan Windows: Konfigurasi aplikasi agar dapat berjalan secara otomatis di latar belakang sebagai layanan sistem Windows, memastikan ketersediaan dan ketahanan.
- Installer dan GUI Kontrol: Pembuatan installer yang profesional dan mudah digunakan untuk mengotomatiskan seluruh proses instalasi, serta pengembangan antarmuka pengguna grafis (GUI) untuk mengelola layanan yang berjalan dan memantau log aplikasi secara real-time.
Bagian 1: Mengemas Aplikasi Node.js TypeScript ke Executable (.exe)
Mengubah aplikasi Node.js menjadi sebuah executable tunggal adalah langkah fundamental untuk distribusi desktop, karena menghilangkan kebutuhan pengguna akhir untuk menginstal Node.js dan dependensi npm secara terpisah. Ini juga menyederhanakan deployment dan memastikan lingkungan runtime yang konsisten.
1.1 Persiapan Proyek Node.js TypeScript
Sebelum memulai proses pengemasan, proyek Node.js TypeScript harus dipersiapkan dengan cermat. Langkah pertama adalah memastikan struktur proyek yang benar dan file package.json yang lengkap, yang mencantumkan semua dependensi proyek, termasuk socket.io untuk komunikasi real-time dan puppeteer untuk otomatisasi browser. Semua dependensi harus telah terinstal dengan menjalankan npm install di root proyek.
Kode TypeScript (.ts) tidak dapat dieksekusi secara langsung oleh runtime Node.js atau alat pengemasan; ia harus dikompilasi terlebih dahulu ke JavaScript (.js). Metode standar untuk mengkompilasi TypeScript adalah dengan tsc (TypeScript Compiler). Pengembang dapat menambahkan skrip build ke package.json mereka, misalnya "build": "tsc --build". Perintah ini akan menghasilkan file JavaScript yang sesuai dengan konfigurasi tsconfig.json, biasanya di direktori dist atau build.1
Sebagai alternatif yang lebih canggih, @vercel/ncc adalah compiler Node.js yang mengkompilasi aplikasi Node.js menjadi satu file JavaScript, termasuk semua dependensi. Pendekatan ini dapat menyederhanakan proses pengemasan lebih lanjut dengan mengurangi jumlah file yang perlu diproses oleh packager.3 Contoh penggunaan
ncc adalah ncc build app.ts -o dist, yang akan menghasilkan satu file index.js (atau nama lain sesuai konfigurasi) di folder dist.
Transformasi kode TypeScript menjadi JavaScript merupakan langkah krusial sebelum pengemasan. Alat pengemasan seperti nexe dirancang untuk membundel kode JavaScript dan dependensinya menjadi sebuah executable. Oleh karena itu, kode TypeScript harus dikonversi menjadi JavaScript agar nexe dapat memprosesnya. Ini bukan sekadar langkah pengembangan biasa, melainkan transformasi fundamental yang diperlukan untuk proses pengemasan. Menggunakan tsc adalah pendekatan langsung, sementara ncc menawarkan kemampuan bundling selama transpilation, yang berpotensi mengoptimalkan ukuran bundle akhir dan menyederhanakan input untuk packager. Ini menunjukkan bahwa proyek TypeScript memerlukan langkah transpilation yang spesifik sebagai prasyarat untuk pengemasan. Pengembang perlu memastikan bahwa tsconfig.json mereka dikonfigurasi dengan benar untuk build produksi, khususnya pada outDir (direktori output untuk JavaScript yang dikompilasi) dan moduleResolution untuk memastikan semua modul terselesaikan dengan benar setelah kompilasi. Langkah ini secara langsung memengaruhi keberhasilan dan efisiensi fase pengemasan berikutnya.
1.2 Pemilihan Alat Packaging: nexe sebagai Solusi Unggul
Memilih alat yang tepat untuk mengemas aplikasi Node.js sangat penting, terutama dengan library kompleks yang memiliki dependensi biner atau struktur file yang tidak biasa, seperti puppeteer. Dua alat populer untuk tujuan ini adalah pkg dan nexe.
pkg adalah alat yang memungkinkan pengemasan proyek Node.js menjadi executable mandiri yang dapat berjalan tanpa Node.js terinstal.4 Alat ini mendukung
cross-compilation untuk berbagai platform (Linux, macOS, Windows) dan dapat menyertakan aset statis. Namun, pkg memiliki masalah yang terdokumentasi dengan baik terkait penanganan deklarasi TypeScript (.d.ts) dan modul ES (ESM), terutama saat berinteraksi dengan versi puppeteer yang lebih baru. pkg cenderung mencoba memproses file .d.ts sebagai kode yang dapat dieksekusi, yang seringkali menyebabkan kesalahan parsing dan build failures.5
Sebaliknya, nexe adalah utilitas baris perintah yang mengkompilasi aplikasi Node.js menjadi satu file executable yang mandiri.7
nexe sering direkomendasikan sebagai alternatif yang lebih modern dan memiliki dukungan yang lebih baik untuk TypeScript dan modul ES yang umum ditemukan di proyek Node.js modern, termasuk yang menggunakan puppeteer.5 Fitur utamanya meliputi kemampuan untuk membuat
self-contained applications, cross-platform builds, dan flexible build pipeline.7
Mengingat penggunaan puppeteer dan TypeScript dalam proyek, nexe adalah pilihan yang lebih kuat dan andal. Masalah pkg dengan ESM dan file .d.ts dapat menyebabkan build failures yang sulit dipecahkan dan runtime errors yang tidak terduga.5 Meskipun ada upaya untuk mengecualikan file
.d.ts di pkg, solusi ini dianggap kurang robust dan hanya menutupi gejala, bukan akar masalahnya.5
nexe dirancang untuk menangani skenario ini dengan lebih baik, menjadikannya pilihan yang lebih stabil untuk aplikasi yang kompleks.
Pemilihan alat pengemasan tidak bersifat generik; hal itu sangat dipengaruhi oleh library spesifik dan fitur bahasa (misalnya, TypeScript, ESM) yang digunakan dalam proyek Node.js. Proyek yang menggunakan puppeteer dan socket.io memiliki persyaratan khusus yang membuat nexe lebih cocok daripada pkg. Ini menunjukkan bahwa kompatibilitas alat pengemasan dengan tumpukan teknologi proyek adalah faktor penentu keberhasilan, dan alat yang berfungsi baik untuk aplikasi Express sederhana mungkin gagal secara signifikan untuk pengaturan puppeteer yang kompleks. Oleh karena itu, pengembang harus melakukan uji tuntas dengan memeriksa kompatibilitas alat pengemasan dengan dependensi proyek spesifik mereka, terutama yang melibatkan komponen native atau persyaratan bundling yang kompleks seperti puppeteer yang menyertakan browsernya sendiri atau bergantung pada browser eksternal. Hal ini dapat menghindari waktu debugging yang signifikan dan memastikan proses build yang berhasil.
1.3 Konfigurasi nexe untuk Aplikasi Node.js TypeScript
Mengemas aplikasi yang menggunakan puppeteer dan socket.io memerlukan konfigurasi nexe yang cermat untuk memastikan semua dependensi, termasuk aset non-JavaScript dan biner, disertakan dengan benar dalam executable akhir.
Langkah pertama adalah menginstal nexe secara global melalui npm: npm install -g nexe.5 Untuk membangun Node.js dari sumber (yang mungkin diperlukan jika
pre-built binaries tidak tersedia untuk target spesifik atau jika diinginkan kustomisasi lebih lanjut), nexe membutuhkan Python 3 (versi 3.7 hingga 3.11) dan Desktop development with C++ workload dari Visual Studio 2022.8 Penting untuk memastikan Python dapat diakses melalui variabel lingkungan
PATH sistem.9
Penanganan puppeteer merupakan aspek yang kompleks. puppeteer secara default mengunduh browser Chromium yang berukuran besar (sekitar 280MB di Windows).10 Mengemas
browser ini secara langsung akan menghasilkan executable yang sangat besar. Untuk mengurangi ukuran bundle secara signifikan, disarankan untuk menggunakan puppeteer-core (versi ringan puppeteer yang tidak menyertakan browser) bersama dengan @sparticuz/chromium (versi Chromium minimal yang dioptimalkan untuk lingkungan serverless).11
Integrasi dengan nexe menantang karena puppeteer perlu menemukan binary Chromium saat aplikasi dijalankan. Secara default, puppeteer mencari browser di ~/.cache/puppeteer 10, yang tidak akan berlaku untuk executable yang dikemas. Oleh karena itu,
puppeteer.launch perlu dikonfigurasi untuk menunjuk ke jalur binary Chromium yang dibundel di dalam executable nexe. nexe dapat menyertakan resources menggunakan opsi -r atau properti resources dalam konfigurasinya.9 Seluruh direktori
node_modules/@sparticuz/chromium atau lokasi spesifik binary Chromium yang diunduh oleh @sparticuz/chromium perlu disertakan sebagai resource.
Berikut adalah contoh adaptasi kode aplikasi di entry point Node.js:
JavaScript
// Pastikan untuk menginstal puppeteer-core dan @sparticuz/chromium
// npm install puppeteer-core @sparticuz/chromium
// npm install -D puppeteer (untuk pengembangan lokal)
import puppeteer from 'puppeteer-core';
import chromium from '@sparticuz/chromium';
import path from 'path';
import fs from 'fs';
async function launchBrowser() {
let executablePath;
// Logika untuk menentukan executablePath di lingkungan nexe
// nexe akan mengekstrak resources ke direktori sementara.
// Anda mungkin perlu menemukan path absolut dari Chromium yang diekstrak.
// Ini adalah bagian yang paling menantang dan mungkin memerlukan eksperimen.
// Sebagai contoh, jika Anda menempatkan chromium di folder 'chromium-binary'
// di root proyek Anda dan menyertakannya sebagai resource:
const bundledChromiumPath = path.join(process.execPath, '..', 'chromium-binary', 'chrome.exe'); // Contoh asumsi
if (fs.existsSync(bundledChromiumPath)) {
executablePath = bundledChromiumPath;
} else {
// Fallback untuk pengembangan atau jika @sparticuz/chromium tidak dapat ditemukan
executablePath = await chromium.executablePath();
}
const browser = await puppeteer.launch({
args: [...chromium.args, '--no-sandbox', '--disable-setuid-sandbox'],
executablePath: executablePath,
headless: chromium.headless,
ignoreHTTPSErrors: true,
});
return browser;
}
Menentukan executablePath yang benar di dalam bundle nexe adalah tantangan signifikan. nexe menyertakan file sebagai virtual filesystem atau mengekstraknya ke lokasi sementara. Pengembang mungkin perlu melakukan runtime detection jalur atau menggunakan nexe's internal APIs (jika tersedia) untuk mengakses binary yang dibundel secara tepat. Ini adalah area yang memerlukan pengujian mendalam.
Meskipun nexe bertujuan untuk menciptakan aplikasi yang "mandiri" 7, ketergantungan
puppeteer pada binary Chromium yang besar memperkenalkan kompleksitas yang melampaui sekadar membundel file JavaScript. Executable Chromium bukanlah file data sederhana; ia harus dapat dieksekusi oleh proses Node.js di dalam bundle nexe. Ini berarti nexe perlu memperlakukan binary ini sebagai resource khusus yang dapat diekstraksi ke lokasi sementara dan kemudian direferensikan dengan benar oleh puppeteer melalui executablePath. Tanpa penanganan yang cermat ini, janji "mandiri" dari nexe untuk aplikasi puppeteer dapat menjadi ilusi, yang menyebabkan kegagalan runtime di mana browser tidak dapat ditemukan. Oleh karena itu, puppeteer yang memiliki ketergantungan biner memerlukan persyaratan bundling yang kompleks, yang jika tidak ditangani dengan benar, dapat menyebabkan masalah runtime. Panduan ini harus secara eksplisit mengarahkan pengguna tentang cara mengkonfigurasi executablePath puppeteer dengan benar untuk menunjuk ke Chromium yang dibundel dalam lingkungan runtime executable nexe. Ini mungkin melibatkan penggunaan mekanisme internal nexe untuk mengakses file yang dibundel atau merancang skrip pembantu kecil di dalam bundle nexe untuk mengekstrak dan meluncurkan Chromium.
Penanganan socket.io juga memerlukan perhatian. socket.io memiliki file klien (socket.io.js, socket.io.min.js) yang biasanya disajikan oleh server ke browser. Saat mengemas aplikasi Node.js ke executable, file-file klien ini tidak secara otomatis disertakan sebagai aset yang dapat diakses oleh aplikasi.6 Oleh karena itu, file-file ini perlu disertakan secara manual sebagai
resources dalam konfigurasi nexe. Misalnya, jika file klien socket.io berada di node_modules/socket.io/client-dist/, file-file tersebut harus ditambahkan ke daftar resources.
Berikut adalah contoh skrip package.json yang mengintegrasikan kompilasi TypeScript, obfuscation (opsional), dan pengemasan nexe:
JSON
{
"name": "nama-proyek-anda",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"build:ts": "tsc --build",
"obfuscate": "javascript-obfuscator./dist --output./dist-obfuscated --config high-obfuscation",
"package:win": "nexe -i./dist-obfuscated/index.js -o myapp.exe -t windows-x64-current --resources \"./public/**/*\" --resources \"./node_modules/socket.io/client-dist/*.js\" --resources \"./node_modules/@sparticuz/chromium/**/*\""
},
"dependencies": {
"socket.io": "^4.x.x",
"puppeteer-core": "^22.x.x",
"@sparticuz/chromium": "^122.x.x"
},
"devDependencies": {
"typescript": "^5.x.x",
"nexe": "^4.x.x",
"javascript-obfuscator": "^4.x.x",
"puppeteer": "^22.x.x"
}
}
Jalur index.js harus menunjuk ke entry point aplikasi setelah kompilasi TypeScript dan/atau obfuscation. Opsi --resources sangat penting untuk menyertakan semua aset non-JavaScript yang diperlukan, termasuk file klien socket.io dan biner puppeteer (Chromium).9
1.4 Proteksi Kode Sumber dengan Obfuscation
Meskipun tidak ada metode yang 100% anti-pembongkaran untuk kode yang berjalan di sisi klien (karena browser atau runtime harus dapat membacanya), obfuscation dapat secara signifikan menghalangi upaya rekayasa balik dan melindungi kekayaan intelektual.
Penting untuk memahami bahwa JavaScript, sebagai bahasa yang diinterpretasikan, pada dasarnya rentan terhadap inspeksi. Jika kode dapat dieksekusi oleh mesin JavaScript, maka dengan alat yang tepat, kode tersebut dapat diekstraksi dari executable (misalnya, hasil nexe) dan di-decompile atau di-deobfuscate.13 Tidak ada "
compiler" sejati untuk JavaScript yang mengubahnya menjadi bahasa tingkat rendah yang sulit direkayasa balik seperti C++.14 Oleh karena itu, proteksi kode JavaScript adalah tentang
membuatnya sangat sulit untuk dibaca dan dipahami, bukan mustahil. Strategi terbaik seringkali melibatkan kombinasi teknik obfuscation dan langkah-langkah hukum (seperti EULA - End User License Agreement).14
Permintaan untuk "proteksi kode" seringkali menyiratkan keinginan untuk menyembunyikan kode sumber sepenuhnya. Namun, berbagai sumber secara konsisten menyatakan bahwa JavaScript, tidak seperti bahasa yang dikompilasi seperti C++, tidak dapat benar-benar "dikompilasi" menjadi bentuk biner yang tidak dapat dibaca. Mesin JavaScript harus dapat menginterpretasikannya. Ini berarti bahwa obfuscation hanya dapat membuat kode lebih sulit untuk direkayasa balik, bukan tidak mungkin. Oleh karena itu, sangat penting untuk menetapkan harapan yang realistis bagi pengguna. Laporan ini harus secara eksplisit menyatakan bahwa obfuscation adalah pencegah, bukan penghalang yang sangat kuat, dan bahwa tindakan hukum (EULA) juga penting untuk perlindungan kekayaan intelektual.
javascript-obfuscator adalah alat open source yang kuat untuk JavaScript dan Node.js, menawarkan berbagai fitur untuk melindungi kode sumber. Fitur-fitur ini meliputi penggantian nama variabel, ekstraksi dan enkripsi string, injeksi kode mati (dead code injection), perataan alur kontrol (control flow flattening), dan kode yang mempertahankan diri (self-defending code) yang mempersulit debugging dan beautification.15
javascript-obfuscator harus dijalankan sebagai langkah setelah kompilasi TypeScript ke JavaScript, dan sebelum pengemasan dengan nexe. Pengguna dapat mengobfuscate file tunggal atau seluruh direktori secara rekursif. Contoh penggunaan CLI: javascript-obfuscator input_file_name.js --output output_file_name.js atau javascript-obfuscator./dist --output./dist-obfuscated.16
javascript-obfuscator menyediakan berbagai opsi untuk mengontrol tingkat dan jenis obfuscation. Pengembang dapat memilih preset yang telah ditentukan (misalnya, low-obfuscation, medium-obfuscation, high-obfuscation) atau menyesuaikan opsi secara manual seperti variables renaming, strings extraction and encryption, dead code injection, control flow flattening, self-defending code, dan debug protection.16 Penting untuk tidak menjalankan
minifier seperti UglifyJS atau Google Closure Compiler pada kode yang sudah di-obfuscate, karena ini dapat merusak fungsionalitas kode (terutama jika fitur self-defending diaktifkan).15
Minifier dapat dijalankan sebelum obfuscation untuk mengoptimalkan ukuran kode awal.
Meskipun javascript-obfuscator menawarkan fitur-fitur canggih seperti "injeksi kode mati," "perataan alur kontrol," dan "kode yang mempertahankan diri" 16, dokumentasi juga mencatat bahwa fitur-fitur ini dapat "secara dramatis meningkatkan ukuran kode" dan "merusak kode" jika
minification lebih lanjut diterapkan.15 Ini menunjukkan adanya pertimbangan penting: tingkat obfuscation yang lebih tinggi dapat menyebabkan peningkatan ukuran kode, potensi eksekusi yang lebih lambat (karena kompleksitas yang ditambahkan), dan
debugging atau pemecahan masalah yang jauh lebih sulit. Oleh karena itu, disarankan untuk menyeimbangkan tingkat proteksi kode yang diinginkan dengan potensi dampak pada kinerja aplikasi dan kemudahan debugging. Untuk deployment produksi yang kritis, obfuscation yang kuat mungkin dipilih, tetapi untuk pengujian internal atau aplikasi yang kurang sensitif, pendekatan yang lebih ringan mungkin lebih praktis untuk menjaga kinerja dan kemampuan debugging.
Bagian 2: Menjalankan Aplikasi sebagai Layanan Windows
Menjalankan aplikasi Node.js sebagai layanan Windows adalah praktik terbaik untuk aplikasi server atau background yang memerlukan ketersediaan tinggi dan operasi tanpa intervensi pengguna. Ini memastikan aplikasi berjalan di latar belakang, otomatis dimulai saat sistem boot, dan dapat dikelola secara terpusat.
2.1 Memahami Layanan Windows untuk Aplikasi Node.js
Layanan Windows menawarkan beberapa keuntungan signifikan untuk aplikasi Node.js yang dirancang untuk berjalan di latar belakang:
- Auto-start: Layanan Windows dapat dikonfigurasi untuk memulai secara otomatis saat sistem boot, bahkan sebelum pengguna login ke sistem.17 Ini krusial untuk aplikasi server yang harus selalu aktif dan tersedia.
- Berjalan di Latar Belakang: Layanan beroperasi di Session 0, sebuah sesi yang terisolasi dan tidak memiliki antarmuka pengguna grafis. Ini berarti aplikasi berjalan tanpa jendela konsol yang terlihat oleh pengguna, memenuhi persyaratan untuk "aplikasi jadi seperti program.exe" yang beroperasi secara diam-diam di latar belakang.17
- Pemulihan Otomatis: Sistem layanan Windows dapat dikonfigurasi untuk secara otomatis me-restart layanan jika mengalami kegagalan, crash, atau berhenti secara tidak terduga.18 Ini meningkatkan ketahanan aplikasi secara signifikan.
- Manajemen Terpusat: Layanan dapat dikelola dengan mudah melalui Windows Services Manager (services.msc) atau melalui perintah CLI (Command Line Interface), memungkinkan kontrol yang konsisten dan terintegrasi dengan sistem operasi.
Pengguna meminta aplikasi berjalan di latar belakang. Meskipun manajer proses Node.js seperti PM2 dapat menjaga aplikasi tetap berjalan di latar belakang 20, mereka biasanya beroperasi dalam sesi pengguna atau memerlukan konfigurasi manual untuk
startup di seluruh sistem. Layanan Windows, di sisi lain, menawarkan integrasi sistem operasi yang lebih dalam: mereka dapat memulai secara otomatis sebelum pengguna mana pun masuk dan menyediakan mekanisme bawaan untuk pemulihan otomatis dari crash.17 Hal ini meningkatkan persyaratan dari sekadar "berjalan di latar belakang" menjadi pencapaian "keandalan dan persistensi tingkat sistem." Untuk
deployment Windows tingkat produksi, menggunakan manajer Layanan Windows native (seperti NSSM atau node-windows) lebih unggul daripada manajer proses khusus Node.js (seperti PM2) karena integrasinya yang lebih dalam dengan OS, memberikan ketahanan yang ditingkatkan, startup otomatis, dan fitur pemulihan.
2.2 Implementasi Layanan dengan node-windows
node-windows adalah pustaka Node.js yang memungkinkan instalasi, pengelolaan, dan uninstal aplikasi Node.js sebagai layanan Windows secara terprogram.18 Pustaka ini berguna jika ingin mengintegrasikan logika layanan langsung ke dalam skrip Node.js.
Untuk memulai, instal pustaka ini di proyek: npm install node-windows.18 Setelah itu, buat skrip Node.js terpisah yang akan dipanggil oleh
installer atau secara manual untuk mengelola layanan. Skrip ini akan menunjuk ke executable nexe yang telah dibuat.
Berikut adalah contoh skrip install-service.js untuk menginstal layanan:
JavaScript
// install-service.js
const Service = require('node-windows').Service;
const path = require('path');
// Jalur ke executable nexe yang sudah dikemas
const appExecutablePath = path.join(process.cwd(), 'myapp.exe'); // Asumsi myapp.exe ada di direktori kerja saat ini
// Buat objek layanan baru
const svc = new Service({
name: 'NamaAplikasiNodeJSAnda', // Nama layanan yang akan muncul di Windows Services
description: 'Deskripsi singkat aplikasi Node.js Anda.',
script: appExecutablePath, // Jalur ke executable nexe Anda
nodeOptions:, // Opsional: Tambahkan opsi Node.js jika diperlukan oleh app.exe
env:
});
// Dengarkan event "install"
svc.on('install', function() {
console.log('Layanan diinstal berhasil.');
svc.start(); // Mulai layanan setelah instalasi
});
// Dengarkan event "alreadyinstalled"
svc.on('alreadyinstalled', function() {
console.log('Layanan sudah terinstal.');
});
// Dengarkan event "invalidinstallation"
svc.on('invalidinstallation', function() {
console.error('Instalasi layanan tidak valid.');
});
// Instal layanan
svc.install();
Dan skrip uninstall-service.js untuk menghapus layanan:
JavaScript
// uninstall-service.js
const Service = require('node-windows').Service;
const path = require('path');
// Buat objek layanan baru (harus sama dengan saat instalasi)
const svc = new Service({
name: 'NamaAplikasiNodeJSAnda',
script: path.join(process.cwd(), 'myapp.exe')
});
// Dengarkan event "uninstall"
svc.on('uninstall', function() {
console.log('Layanan di-uninstal berhasil.');
console.log('Layanan ada:', svc.exists); // Harusnya false
});
// Dengarkan event "notfound"
svc.on('notfound', function() {
console.log('Layanan tidak ditemukan.');
});
// Uninstal layanan
svc.uninstall();
Skrip ini akan dipanggil oleh installer untuk mengotomatiskan proses instalasi dan uninstal layanan.
2.3 Alternatif: NSSM (Non-Sucking Service Manager)
Sebagai alternatif untuk node-windows, NSSM (Non-Sucking Service Manager) adalah alat pihak ketiga yang sangat direkomendasikan untuk menjalankan aplikasi apa pun sebagai layanan Windows.21 NSSM dikenal karena kemudahan penggunaan, ukuran kecil, dan kemampuannya untuk mengelola berbagai jenis executable, termasuk Node.js, Python, Java, dan PHP.22
Keunggulan NSSM:
- Fleksibilitas: NSSM dapat menjalankan executable apa pun, tidak hanya aplikasi yang dirancang khusus sebagai layanan Windows.19
- Konfigurasi Mudah: NSSM menyediakan antarmuka GUI dan CLI untuk menginstal, mengkonfigurasi, dan mengelola layanan.19 Ini memungkinkan pengaturan direktori kerja khusus, prioritas proses,
logging, pemeriksaan kesehatan, variabel lingkungan, dan skrip pra-peluncuran.19
- Pemantauan dan Pemulihan: NSSM terus memantau aplikasi, secara otomatis me-restart jika crash, hang, atau berhenti.19 Ini menjadikannya pilihan yang sangat andal untuk menjaga aplikasi non-layanan tetap berjalan di latar belakang.
- Log Otomatis: NSSM dapat mengalihkan stdout dan stderr ke file log dengan rotasi otomatis berbasis ukuran.19
Instalasi dan Penggunaan NSSM:
- Unduh NSSM: Unduh NSSM dari situs web resminya (misalnya, dari SourceForge). Ini adalah utilitas mandiri yang tidak memerlukan instalasi.22
- Instal Layanan (CLI): Buka Command Prompt sebagai Administrator dan navigasi ke direktori NSSM. Gunakan perintah berikut:
Bash
nssm install [NamaLayananAnda][path_ke_executable_nexe_anda]
Contoh:
Bash
nssm install MyNodeAppService C:\Path\To\Your\myapp.exe
Ini akan membuka GUI NSSM di mana Anda dapat mengkonfigurasi detail layanan, seperti nama, deskripsi, direktori startup, dan argumen.22
- Mulai Layanan:
Bash
nssm start MyNodeAppService
- Hentikan Layanan:
Bash
nssm stop MyNodeAppService
- Uninstal Layanan:
Bash
nssm remove MyNodeAppService
NSSM adalah pilihan yang kuat dan seringkali lebih sederhana untuk mengelola executable yang dikemas sebagai layanan Windows, terutama jika tidak ingin mengintegrasikan logika layanan langsung ke dalam kode Node.js menggunakan node-windows.
Bagian 3: Membangun Installer Windows
Setelah aplikasi Node.js dikemas menjadi executable dan skrip layanan disiapkan, langkah selanjutnya adalah membuat installer Windows yang profesional. Installer ini akan mengotomatiskan seluruh proses instalasi, termasuk menempatkan file aplikasi, menginstal layanan Windows, dan membuat pintasan. NSIS (Nullsoft Scriptable Install System) dan Inno Setup adalah dua alat open-source yang sangat populer dan fleksibel untuk tujuan ini.
3.1 Pemilihan Alat Installer: NSIS atau Inno Setup
Baik NSIS maupun Inno Setup adalah pilihan yang sangat baik untuk membuat installer Windows. Keduanya menawarkan kemampuan scripting yang kuat untuk menangani tugas instalasi yang kompleks.
NSIS (Nullsoft Scriptable Install System):
- Fitur Utama: NSIS adalah sistem open source profesional untuk membuat installer Windows. NSIS dirancang agar sekecil dan sefleksibel mungkin, sehingga sangat cocok untuk distribusi internet.23 NSIS berbasis skrip dan memungkinkan pembuatan logika untuk menangani tugas instalasi yang paling kompleks.23 Banyak
plug-in dan skrip sudah tersedia, memungkinkan pembuatan web installer, komunikasi dengan Windows dan komponen perangkat lunak lainnya, serta instalasi atau pembaruan komponen bersama.23
- Kelebihan: Ukuran overhead yang sangat kecil, komunitas yang besar, dan banyak contoh kode.24 NSIS juga dapat membuat
installer di Linux/macOS melalui cross-compilation jika NSSIS terinstal.25
- Kekurangan: Bahasa skripnya sendiri mungkin memerlukan kurva pembelajaran.
Inno Setup:
- Fitur Utama: Inno Setup adalah builder installer open-source untuk aplikasi Windows yang telah dipercaya oleh pengembang dan organisasi sejak 1997.26 Inno Setup mendukung pembuatan satu file EXE untuk distribusi
online yang mudah, antarmuka wizard Windows standar yang dapat disesuaikan, kemampuan uninstal lengkap, dan berbagai opsi instalasi file termasuk kompresi.26 Inno Setup juga mendukung instalasi multibahasa, instalasi yang dilindungi kata sandi dan dienkripsi, instalasi yang ditandatangani secara digital, dan instalasi
silent.26 Inno Setup memiliki opsi
preprocessor terintegrasi untuk kustomisasi waktu kompilasi tingkat lanjut dan mesin scripting Pascal terintegrasi untuk kustomisasi runtime instalasi dan uninstal tingkat lanjut.26
- Kelebihan: Antarmuka wizard yang mudah digunakan untuk membuat skrip dasar, dukungan scripting Pascal yang kuat untuk logika kompleks, dan banyak fitur bawaan untuk instalasi aplikasi.26 Digunakan oleh proyek besar seperti Microsoft Visual Studio Code.26
- Kekurangan: Bahasa scripting Pascal mungkin asing bagi pengembang Node.js.
Untuk tujuan panduan ini, Inno Setup akan digunakan karena kemudahan penggunaan wizard untuk setup dasar dan kemampuan scripting Pascal yang kuat untuk kustomisasi yang lebih kompleks, termasuk instalasi layanan Windows.
3.2 Membuat Skrip Installer dengan Inno Setup
Setelah Inno Setup diinstal (dapat diunduh dari situs web resminya atau diinstal melalui winget: winget install --id JRSoftware.InnoSetup -e -s winget -i 29), langkah selanjutnya adalah membuat skrip
.iss yang akan mendefinisikan perilaku installer.
Struktur Dasar Skrip .iss:
Cuplikan kode
; Nama file: myapp-installer.iss
AppName=Nama Aplikasi Node.js Anda
AppVersion=1.0.0
DefaultDirName={autopf}\NamaAplikasiNodeJSAnda
DefaultGroupName=Nama Aplikasi Node.js Anda
OutputDir=OutputInstaller
OutputBaseFilename=NamaAplikasiNodeJSAnda-Setup
Compression=lzma2
SolidCompression=yes
WizardStyle=modern
SetupIconFile=path\to\your\app\icon.ico ; Opsional: ikon installer
UninstallDisplayIcon={app}\myapp.exe ; Ikon untuk uninstaller
DisableProgramGroupPage=yes ; Tidak menampilkan halaman grup program
PrivilegesRequired=admin ; Membutuhkan hak akses administrator untuk instalasi
[Files]
; Sertakan executable nexe Anda
Source: "path\to\your\myapp.exe"; DestDir: "{app}"; Flags: ignoreversion replacesameversion
; Sertakan file-file lain yang diperlukan oleh aplikasi Anda (misalnya, aset, konfigurasi)
; Jika ada folder 'public' di root aplikasi Anda:
Source: "path\to\your\public\*"; DestDir: "{app}\public"; Flags: recursesubdirs createallsubdirs
; Sertakan skrip instalasi/uninstal layanan dari node-windows
Source: "path\to\your\install-service.js"; DestDir: "{app}"; Flags: ignoreversion replacesameversion
Source: "path\to\your\uninstall-service.js"; DestDir: "{app}"; Flags: ignoreversion replacesameversion
[Icons]
; Buat pintasan di Start Menu
Name: "{group}\Nama Aplikasi Node.js Anda"; Filename: "{app}\myapp.exe"; WorkingDir: "{app}"; Parameters: "--start-gui" ; Parameter untuk memulai GUI
Name: "{group}\Start Service"; Filename: "{app}\node.exe"; Parameters: "{app}\install-service.js"; WorkingDir: "{app}"; Flags: runhidden ; Pintasan untuk memulai layanan
Name: "{group}\Stop Service"; Filename: "{app}\node.exe"; Parameters: "{app}\uninstall-service.js"; WorkingDir: "{app}"; Flags: runhidden ; Pintasan untuk menghentikan layanan
Name: "{group}\Lihat Log"; Filename: "{app}\LogViewer.exe"; WorkingDir: "{app}"; Parameters: "path\to\your\log.log" ; Pintasan untuk melihat log (jika ada GUI viewer)
; Jalankan skrip instalasi layanan setelah instalasi selesai
Filename: "{app}\node.exe"; Parameters: "{app}\install-service.js"; Flags: runhidden postinstall; StatusMsg: "Menginstal Layanan Windows...";
; Atau jika menggunakan NSSM:
; Filename: "{app}\nssm.exe"; Parameters: "install MyNodeAppService ""{app}\myapp.exe"""; Flags: runhidden postinstall; StatusMsg: "Menginstal Layanan Windows...";
; Filename: "{app}\nssm.exe"; Parameters: "start MyNodeAppService"; Flags: runhidden postinstall; StatusMsg: "Memulai Layanan Windows...";
; Jalankan skrip uninstal layanan sebelum uninstal file
Filename: "{app}\node.exe"; Parameters: "{app}\uninstall-service.js"; Flags: runhidden; StatusMsg: "Meng-uninstal Layanan Windows...";
; Atau jika menggunakan NSSM:
; Filename: "{app}\nssm.exe"; Parameters: "stop MyNodeAppService"; Flags: runhidden; StatusMsg: "Menghentikan Layanan Windows...";
; Filename: "{app}\nssm.exe"; Parameters: "remove MyNodeAppService confirm"; Flags: runhidden; StatusMsg: "Menghapus Layanan Windows...";
; Opsional: Tambahkan opsi untuk menginstal Node.js runtime jika belum ada
Name: "installnodejs"; Description: "Install Node.js runtime (if not present)"; GroupDescription: "Dependencies:";
Penjelasan Skrip:
- ``: Mendefinisikan metadata aplikasi, direktori instalasi default, nama grup program, dan opsi kompresi.28
PrivilegesRequired=admin penting karena instalasi layanan Windows memerlukan hak administrator.
- [Files]: Mencantumkan semua file dan direktori yang akan disertakan dalam installer dan tujuan mereka di sistem pengguna. Ini harus mencakup executable myapp.exe yang dihasilkan oleh nexe, serta skrip install-service.js dan uninstall-service.js.28 Jika aplikasi memiliki aset lain (misalnya, file HTML, CSS, gambar untuk
frontend atau puppeteer), file-file tersebut juga harus disertakan di sini.
- [Icons]: Membuat pintasan di Start Menu Windows. Pintasan untuk "Start Service" dan "Stop Service" akan memanggil skrip Node.js yang relevan atau perintah NSSM secara hidden.24
- ``: Bagian ini sangat penting untuk mengotomatisasi instalasi layanan. Setelah semua file disalin, installer akan menjalankan skrip install-service.js menggunakan runtime Node.js yang dibundel (atau NSSM) untuk menginstal dan memulai layanan Windows.28 Opsi
runhidden mencegah jendela konsol muncul selama instalasi.
- ``: Mendefinisikan perintah yang akan dijalankan saat pengguna meng-uninstal aplikasi. Ini akan menghentikan dan menghapus layanan Windows yang telah diinstal.24
3.3 Membundel Runtime Node.js dan Executable nexe
Salah satu persyaratan utama adalah agar installer mengurus semua kebutuhan aplikasi, termasuk runtime Node.js. Dengan menggunakan nexe, runtime Node.js sudah dibundel ke dalam myapp.exe.7 Ini berarti
installer tidak perlu menginstal Node.js secara terpisah di sistem pengguna.
Inno Setup akan mengemas executable myapp.exe yang dihasilkan oleh nexe sebagai file utama. Ketika myapp.exe dijalankan (baik secara langsung atau sebagai layanan), ia sudah berisi runtime Node.js dan kode aplikasi Anda. Ini menyederhanakan proses instalasi secara signifikan karena tidak ada dependensi Node.js eksternal yang perlu dikelola oleh installer.31
Langkah-langkah Kompilasi Installer:
- Buka Inno Setup IDE: Buka Inno Setup Compiler.
- Buka Skrip: Buka file .iss yang telah dibuat.
- Kompilasi: Klik tombol "Compile" (biasanya ikon play hijau atau "Build" -> "Compile") di Inno Setup IDE.
Output:
Inno Setup akan mengkompilasi skrip dan menghasilkan file .exe
installer
di direktori OutputDir yang ditentukan dalam skrip .iss.28
Bagian 4: Antarmuka Pengguna Grafis (GUI) untuk Kontrol Layanan dan Log
Untuk menggantikan interaksi manual melalui terminal (npm run dev/start) dan memberikan pengalaman pengguna yang lebih baik, diperlukan GUI sederhana yang memungkinkan pengguna untuk memulai, menghentikan, me-restart layanan, dan melihat log konsol secara real-time. Electron adalah kerangka kerja yang sangat cocok untuk tugas ini karena memungkinkan pembangunan aplikasi desktop cross-platform menggunakan teknologi web (JavaScript, HTML, CSS) dan memiliki akses penuh ke API Node.js, termasuk modul child_process untuk berinterinteraksi dengan layanan sistem.32
4.1 Membangun GUI dengan Electron
Electron menggabungkan Chromium dan Node.js, memungkinkan pembuatan antarmuka pengguna native dengan teknologi web.33 Ini sangat ideal untuk mengontrol layanan Windows dan menampilkan log.
Struktur Proyek Electron:
- Buat proyek Electron baru: npm init electron-app@latest my-service-gui.33
- Struktur dasar akan mencakup main.js (proses utama Electron) dan index.html (antarmuka pengguna).
Kontrol Layanan Windows dari Electron:
Proses utama Electron dapat menggunakan modul child_process Node.js untuk berinteraksi dengan layanan Windows. Ini akan memanggil perintah sc (Service Control) bawaan Windows atau perintah NSSM/node-windows yang telah diinstal.
- main.js (Proses Utama Electron):
const { app, BrowserWindow, ipcMain } = require('electron'); const { exec } = require('node:child_process'); // Menggunakan exec untuk menjalankan perintah shell const path = require('path'); const fs = require('fs'); let mainWindow; const SERVICE_NAME = 'NamaAplikasiNodeJSAnda'; // Harus sama dengan nama layanan di Inno Setup / node-windows const LOG_FILE_PATH = path.join(app.getPath('userData'), 'logs', 'main.log'); // Jalur log aplikasi Node.js function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), // Skrip preload untuk komunikasi IPC nodeIntegration: false, // Penting untuk keamanan contextIsolation: true // Penting untuk keamanan } }); mainWindow.loadFile('index.html'); // mainWindow.webContents.openDevTools(); // Untuk debugging } app.whenReady().then(() => { createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); app.on('window-all-closed', () => { if (process.platform!== 'darwin') { app.quit(); } }); // Handler IPC untuk kontrol layanan ipcMain.handle('service-control', async (event, action) => { let command = ''; switch (action) { case 'start': command = `sc start ${SERVICE_NAME}`; break; case 'stop': command = `sc stop ${SERVICE_NAME}`; break; case 'restart': command = `sc stop ${SERVICE_NAME} && sc start ${SERVICE_NAME}`; break; case 'status': command = `sc query ${SERVICE_NAME}`; break; default: return { success: false, message: 'Aksi tidak dikenal.' }; } return new Promise((resolve) => { exec(command, (error, stdout, stderr) => { if (error) { console.error(`Error executing command: ${error.message}`); resolve({ success: false, message: stderr | | error.message }); return; } if (stderr) { console.warn(Command stderr: ${stderr}); resolve({ success: false, message: stderr }); return; } console.log(Command stdout: ${stdout}); resolve({ success: true, message: stdout }); }); }); }); // Handler IPC untuk membaca log ipcMain.handle('read-log', async () => { try { if (fs.existsSync(LOG_FILE_PATH)) { // Membaca 100 baris terakhir dari file log const logContent = fs.readFileSync(LOG_FILE_PATH, 'utf8'); const lines = logContent.split('\n'); const last100Lines = lines.slice(Math.max(lines.length - 100, 0)).join('\n'); return { success: true, content: last100Lines }; } else { return { success: false, message: 'File log tidak ditemukan.' }; } } catch (error) { console.error(`Error reading log file: ${error.message}`); return { success: false, message: error.message }; } }); // Handler IPC untuk tail log secara real-time ipcMain.handle('tail-log-start', (event) => { if (!fs.existsSync(LOG_FILE_PATH)) { event.sender.send('log-update', 'File log tidak ditemukan.'); return; } // Menggunakan fs.watchFile untuk memantau perubahan file fs.watchFile(LOG_FILE_PATH, { interval: 1000 }, (curr, prev) => { if (curr.mtime > prev.mtime) { // File telah dimodifikasi, baca perubahan baru const newContent = fs.readFileSync(LOG_FILE_PATH, 'utf8'); const lines = newContent.split('\n'); const last100Lines = lines.slice(Math.max(lines.length - 100, 0)).join('\n'); event.sender.send('log-update', last100Lines); } }); }); ipcMain.handle('tail-log-stop', () => { fs.unwatchFile(LOG_FILE_PATH); });
preload.js (Skrip Pra-muat Electron):
const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("electronAPI", { serviceControl: (action) => ipcRenderer.invoke("service-control", action), readLog: () => ipcRenderer.invoke("read-log"), tailLogStart: () => ipcRenderer.invoke("tail-log-start"), tailLogStop: () => ipcRenderer.invoke("tail-log-stop"), onLogUpdate: (callback) => ipcRenderer.on("log-update", (event, data) => callback(data)), });
- index.html (Antarmuka Pengguna Electron):
<!DOCTYPE **html**> <html> <head> <meta charset="UTF-8" /> <title>Kontrol Aplikasi Node.js</title> <style> body { font-family: sans-serif; padding: 20px; } button { margin: 5px; padding: 10px 15px; cursor: pointer; } #log-output { width: 100%; height: 300px; border: 1px solid #ccc; padding: 10px; overflow-y: scroll; background-color: #f9f9f9; font-family: monospace; white-space: pre-wrap; } </style> </head> <body> <h1>Kontrol Layanan Node.js</h1> <div> <button id="start-btn">Mulai Layanan</button> <button id="stop-btn">Hentikan Layanan</button> <button id="restart-btn">Restart Layanan</button> <button id="status-btn">Cek Status</button> </div> <p id="service-status"></p> <h2>Log Konsol</h2> <div> <button id="refresh-log-btn">Refresh Log</button> <button id="tail-log-btn">Mulai Tail Log Real-time</button> <button id="stop-tail-log-btn">Hentikan Tail Log</button> </div> <pre id="log-output"></pre> <script> const startBtn = document.getElementById('start-btn'); const stopBtn = document.getElementById('stop-btn'); const restartBtn = document.getElementById('restart-btn'); const statusBtn = document.getElementById('status-btn'); const serviceStatus = document.getElementById('service-status'); const logOutput = document.getElementById('log-output'); const refreshLogBtn = document.getElementById('refresh-log-btn'); const tailLogBtn = document.getElementById('tail-log-btn'); const stopTailLogBtn = document.getElementById('stop-tail-log-btn'); async function controlService(action) { const result = await window.electronAPI.serviceControl(action); serviceStatus.textContent = `Status: ${result.message}`; if (!result.success) { serviceStatus.style.color = 'red'; } else { serviceStatus.style.color = 'green'; } } async function readAndDisplayLog() { const result = await window.electronAPI.readLog(); if (result.success) { logOutput.textContent = result.content; logOutput.scrollTop = logOutput.scrollHeight; // Scroll ke bawah } else { logOutput.textContent = `Error: ${result.message}`; } } startBtn.addEventListener('click', () => controlService('start')); stopBtn.addEventListener('click', () => controlService('stop')); restartBtn.addEventListener('click', () => controlService('restart')); statusBtn.addEventListener('click', () => controlService('status')); refreshLogBtn.addEventListener('click', readAndDisplayLog); let isTailing = false; tailLogBtn.addEventListener('click', () => { if (!isTailing) { window.electronAPI.tailLogStart(); window.electronAPI.onLogUpdate((data) => { logOutput.textContent = data; logOutput.scrollTop = logOutput.scrollHeight; }); isTailing = true; tailLogBtn.disabled = true; stopTailLogBtn.disabled = false; serviceStatus.textContent = 'Mulai tailing log real-time...'; serviceStatus.style.color = 'blue'; } }); stopTailLogBtn.addEventListener('click', () => { if (isTailing) { window.electronAPI.tailLogStop(); isTailing = false; tailLogBtn.disabled = false; stopTailLogBtn.disabled = true; serviceStatus.textContent = 'Tailing log dihentikan.'; serviceStatus.style.color = 'black'; } }); // Baca log saat aplikasi dimuat readAndDisplayLog(); </script> </body> </html>
Penjelasan Integrasi:
- Komunikasi IPC: Electron menggunakan Inter-Process Communication (IPC) untuk berkomunikasi antara proses utama (Node.js) dan proses renderer (browser Chromium).34 Skrip
preload.js mengekspos API ke window objek di renderer yang memungkinkan tombol di index.html memanggil fungsi di main.js.
- Kontrol Layanan: Fungsi serviceControl di main.js menggunakan child_process.exec untuk menjalankan perintah sc (Service Control) Windows.35 Perintah ini dapat memulai, menghentikan, me-restart, atau memeriksa status layanan Windows yang telah diinstal.
- Melihat Log Konsol:
- Perekaman Log: Aplikasi Node.js yang berjalan sebagai layanan harus dikonfigurasi untuk menulis log ke file. Ini dapat dilakukan dengan mengalihkan stdout dan stderr ke file saat layanan dimulai, atau menggunakan library logging seperti winston atau log4js.36 Misalnya, di skrip
entry point Node.js Anda, Anda dapat mengalihkan process.stdout.write dan process.stderr.write ke fs.createWriteStream.36
- Pembacaan Log Real-time: Proses renderer Electron tidak dapat langsung membaca file sistem. Oleh karena itu, permintaan untuk membaca log dikirim ke proses utama melalui IPC (read-log). Proses utama kemudian membaca file log dan mengirimkan isinya kembali ke renderer.34 Untuk pembaruan
real-time, fs.watchFile dapat digunakan di proses utama untuk memantau perubahan pada file log dan mengirimkan pembaruan ke renderer melalui ipcRenderer.send.39
electron-log juga merupakan library yang sangat berguna untuk mengelola log di aplikasi Electron, secara otomatis menulis log ke lokasi standar dan memungkinkan akses dari proses utama dan renderer.41
- Tampilan Log: Log ditampilkan dalam elemen <pre> di index.html, yang mempertahankan format teks asli. Scrolling otomatis ke bawah memastikan pengguna selalu melihat log terbaru.
4.2 Mengemas GUI Electron
GUI Electron juga perlu dikemas menjadi executable terpisah. Electron Forge adalah alat yang direkomendasikan untuk mengemas dan mempublikasikan aplikasi Electron.33
Langkah-langkah Pengemasan Electron GUI:
- Instal Electron Forge:
npm install --save-dev @electron-forge/cli
npx electron-forge import
- Konfigurasi package.json: Electron Forge akan menambahkan skrip dan konfigurasi ke package.json Anda.
- Build Aplikasi:
npm run make
Perintah ini akan menghasilkan installer (misalnya, .exe atau .msi untuk Windows) untuk aplikasi GUI Anda di direktori out/make.33
GUI Electron yang dihasilkan akan menjadi executable terpisah yang akan diinstal bersama dengan aplikasi Node.js utama oleh installer Inno Setup. GUI ini akan berfungsi sebagai dashboard kontrol untuk layanan Node.js yang berjalan di latar belakang.
Kesimpulan dan Rekomendasi
Mendistribusikan aplikasi Node.js TypeScript yang kompleks dengan socket.io dan puppeteer sebagai produk Windows yang mandiri memerlukan pendekatan multi-langkah yang cermat. Proses ini melibatkan kompilasi kode TypeScript, pengemasan aplikasi menjadi executable tunggal, implementasi proteksi kode, konfigurasi aplikasi sebagai layanan Windows yang tangguh, dan pengembangan antarmuka pengguna grafis untuk kontrol dan pemantauan log.
Kesimpulan Utama:
- Pengemasan yang Efisien: Penggunaan nexe adalah pilihan yang lebih unggul dibandingkan pkg untuk aplikasi Node.js yang melibatkan TypeScript dan library dengan dependensi biner seperti puppeteer. nexe menawarkan dukungan yang lebih baik untuk struktur modul modern dan penanganan resource. Namun, penanganan binary Chromium puppeteer di dalam bundle nexe memerlukan konfigurasi jalur yang cermat pada saat runtime untuk memastikan browser dapat ditemukan dan diluncurkan dengan benar.
- Proteksi Kode yang Realistis: Obfuscation JavaScript dengan alat seperti javascript-obfuscator dapat secara signifikan menghalangi rekayasa balik, tetapi tidak dapat sepenuhnya mencegahnya karena sifat bahasa yang diinterpretasikan. Kombinasi obfuscation dengan perjanjian lisensi pengguna akhir (EULA) adalah strategi yang lebih komprehensif untuk melindungi kekayaan intelektual. Penting untuk menyeimbangkan tingkat obfuscation dengan dampak potensial pada kinerja dan kemudahan debugging.
- Ketahanan Layanan: Menjalankan aplikasi Node.js sebagai layanan Windows menggunakan node-windows atau NSSM memberikan keandalan yang jauh lebih tinggi dibandingkan hanya menjalankan proses di latar belakang. Layanan dapat memulai secara otomatis saat sistem boot dan pulih dari kegagalan, memastikan ketersediaan aplikasi yang berkelanjutan. NSSM menawarkan fleksibilitas yang lebih besar dan kemudahan konfigurasi untuk mengelola executable apa pun sebagai layanan.
- Pengalaman Pengguna yang Ditingkatkan: Pengembangan GUI berbasis Electron menyediakan antarmuka yang intuitif bagi pengguna akhir untuk mengontrol layanan (memulai, menghentikan, me-restart) dan memantau log secara real-time, menggantikan kebutuhan akan interaksi baris perintah yang kompleks. Komunikasi IPC antara proses utama Electron dan renderer memungkinkan interaksi yang mulus dengan layanan sistem dan pembacaan file log.
- Installer Profesional: NSIS atau Inno Setup memungkinkan pembuatan installer Windows yang profesional dan otomatis, yang dapat membundel executable aplikasi, skrip layanan, dan GUI kontrol menjadi satu paket yang mudah didistribusikan.
Rekomendasi:
- Validasi Jalur Puppeteer: Lakukan pengujian ekstensif untuk memastikan puppeteer dapat menemukan dan meluncurkan binary Chromium yang dibundel di dalam executable nexe pada berbagai lingkungan Windows. Ini mungkin melibatkan penyesuaian logika penentuan jalur runtime dalam kode aplikasi Node.js.
- Strategi Logging: Terapkan library logging yang kuat seperti winston atau electron-log dalam aplikasi Node.js Anda untuk memastikan semua output konsol dicatat ke file dengan format yang konsisten. Ini akan mempermudah pemantauan dan debugging melalui GUI Electron.
- Pengujian Komprehensif: Lakukan pengujian menyeluruh terhadap seluruh alur, mulai dari instalasi installer, fungsionalitas layanan (start/stop/restart), hingga tampilan log real-time di GUI. Uji pada berbagai versi dan arsitektur Windows yang ditargetkan.
- Dokumentasi Pengguna: Sertakan dokumentasi yang jelas untuk pengguna akhir mengenai cara menginstal, menjalankan, dan mengelola aplikasi melalui GUI, serta lokasi file log untuk pemecahan masalah.
- Pertimbangan Keamanan: Meskipun obfuscation membantu, untuk data sensitif atau logika bisnis yang sangat kritis, pertimbangkan untuk mengimplementasikan bagian-bagian tertentu dari aplikasi sebagai layanan backend yang dihosting di server yang dikendalikan, dan hanya mengekspos API yang diperlukan ke aplikasi desktop. Ini memberikan lapisan keamanan tambahan yang tidak dapat dicapai hanya dengan proteksi kode klien.
Dengan mengikuti panduan ini, pengembang dapat berhasil mengubah proyek Node.js TypeScript mereka menjadi produk Windows yang profesional dan siap didistribusikan, memenuhi kebutuhan pengguna akan aplikasi yang mandiri, terlindungi, dan mudah dikelola.
Karya yang dikutip
- Compile and build TypeScript code using npm - Visual Studio (Windows) | Microsoft Learn, diakses Agustus 18, 2025, https://learn.microsoft.com/en-us/visualstudio/javascript/compile-typescript-code-npm?view=vs-2022
- How to set up TypeScript, diakses Agustus 18, 2025, https://www.typescriptlang.org/download/
- How to make exe files from a node.js app? - Stack Overflow, diakses Agustus 18, 2025, https://stackoverflow.com/questions/8173232/how-to-make-exe-files-from-a-node-js-app
- vercel/pkg: Package your Node.js project into an executable - GitHub, diakses Agustus 18, 2025, https://github.com/vercel/pkg
- Packaging error with pkg tool when updating puppeteer from v1.20.0 to v24.0.0, diakses Agustus 18, 2025, https://community.latenode.com/t/packaging-error-with-pkg-tool-when-updating-puppeteer-from-v1-20-0-to-v24-0-0/32518
- How to use with `pkg` - Socket.IO, diakses Agustus 18, 2025, https://socket.io/how-to/use-with-pkg
- nexe/nexe: create a single executable out of your node.js apps - GitHub, diakses Agustus 18, 2025, https://github.com/nexe/nexe
- Node.js Packaging - Tutorialspoint, diakses Agustus 18, 2025, https://www.tutorialspoint.com/nodejs/nodejs_packaging.htm
- nexe - NPM, diakses Agustus 18, 2025, https://www.npmjs.com/package/nexe
- Installation - Puppeteer, diakses Agustus 18, 2025, https://pptr.dev/guides/installation
- Deploying Puppeteer with Next.js on Vercel, diakses Agustus 18, 2025, https://vercel.com/guides/deploying-puppeteer-with-nextjs-on-vercel
- Running Puppeteer on Vercel - Medium, diakses Agustus 18, 2025, https://medium.com/@ubermensch1/running-puppeteer-on-vercel-511dfec154a1
- Hide source code possibility · Issue #269 · nwjs/nw.js - GitHub, diakses Agustus 18, 2025, https://github.com/nwjs/nw.js/issues/269
- how to Hide source code from build executable in electron-app : r/electronjs - Reddit, diakses Agustus 18, 2025, https://www.reddit.com/r/electronjs/comments/dts5ri/how_to_hide_source_code_from_build_executable_in/
- JavaScript Obfuscator Tool, diakses Agustus 18, 2025, https://obfuscator.io/
- A powerful obfuscator for JavaScript and Node.js - GitHub, diakses Agustus 18, 2025, https://github.com/javascript-obfuscator/javascript-obfuscator
- How to Run Any Node.js Application as a Windows Service with AlwaysUp, diakses Agustus 18, 2025, https://www.coretechnologies.com/products/AlwaysUp/Apps/RunNodeJSAsAService.html
- Set Up a Node.js Backend as a Windows Service | by Gul Ershad | Medium, diakses Agustus 18, 2025, https://mailtogulershad.medium.com/set-up-a-node-js-backend-as-a-windows-service-a9b17bf7403f
- aelassas/servy: Run Any App as a Windows Service — A Fully Managed NSSM Alternative, diakses Agustus 18, 2025, https://github.com/aelassas/servy
- How to Start and Run a Node.js Service in the Background using PM2 - GitHub Gist, diakses Agustus 18, 2025, https://gist.github.com/bewithdhanu/a392f61d35edf5eef8e27dc5b84753d0
- How to install node.js as windows service? - Stack Overflow, diakses Agustus 18, 2025, https://stackoverflow.com/questions/10547974/how-to-install-node-js-as-windows-service
- How do you run a Python script as a service in Windows? [closed] - Stack Overflow, diakses Agustus 18, 2025, https://stackoverflow.com/questions/32404/how-do-you-run-a-python-script-as-a-service-in-windows
- NSIS Wiki, diakses Agustus 18, 2025, https://nsis.sourceforge.io/Main_Page
- Category:Code Examples - NSIS - SourceForge, diakses Agustus 18, 2025, https://nsis.sourceforge.io/Category:Code_Examples
- Windows Installer - Tauri, diakses Agustus 18, 2025, https://v2.tauri.app/distribute/windows-installer/
- Inno Setup - JRSoftware.org, diakses Agustus 18, 2025, https://jrsoftware.org/isinfo.php
- Inno Setup Help - JRSoftware.org, diakses Agustus 18, 2025, https://jrsoftware.org/ishelp/
- Create Windows Installer for Node.js App using Inno Setup - Prakhar's blog, diakses Agustus 18, 2025, https://prakhartripathi.hashnode.dev/create-windows-installer-for-nodejs-app-using-inno-setup
- Inno Setup Downloads - JRSoftware.org, diakses Agustus 18, 2025, https://jrsoftware.org/isdl.php
- How to create a Windows (InnoSetup exe) installer (for NodeJS apps) - AJ ONeal, diakses Agustus 18, 2025, https://coolaj86.com/articles/how-to-create-an-innosetup-installer.html
- Remove the need for users to set up Node.js themselves · Issue #24 · asamuzaK/withExEditorHost - GitHub, diakses Agustus 18, 2025, https://github.com/asamuzaK/withExEditorHost/issues/24
- Building your First App | Electron, diakses Agustus 18, 2025, https://electronjs.org/docs/latest/tutorial/tutorial-first-app
- Electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS, diakses Agustus 18, 2025, https://electronjs.org/
- Electron JS Read/Write to Locale File | by Sagar Hudge - Medium, diakses Agustus 18, 2025, https://medium.com/@sagar.hudge/electron-js-read-write-to-locale-file-711c230c798e
- Child process | Node.js v24.6.0 Documentation, diakses Agustus 18, 2025, https://nodejs.org/api/child_process.html
- How to configure Node.js to log to a file instead of the console? - LambdaTest Community, diakses Agustus 18, 2025, https://community.lambdatest.com/t/how-to-configure-node-js-to-log-to-a-file-instead-of-the-console/35551
- redirect node.js console output to file - GitHub Gist, diakses Agustus 18, 2025, https://gist.github.com/eddex/520c065156b5b1fc3f7e17278b52fb9f
- How to Create API to View Logs in Node.js ? - GeeksforGeeks, diakses Agustus 18, 2025, https://www.geeksforgeeks.org/node-js/how-to-create-api-to-view-logs-in-node-js/
- Using tail -F to see a file changing in real-time - Stack Overflow, diakses Agustus 18, 2025, https://stackoverflow.com/questions/41756525/using-tail-f-to-see-a-file-changing-in-real-time
- Live log tail with Logdy - stream logs from anywhere to web browser, diakses Agustus 18, 2025, https://logdy.dev/blog/post/live-log-tail-with-logdy-stream-logs-from-anywhere-to-web-browser
- electron-log - NPM, diakses Agustus 18, 2025, https://www.npmjs.com/package/electron-log
- Author:nidzammst
- URL:https://nidzammst.vercel.app/article/mengemas-aplikasi-nodejs-ke-installer-windows-exe-dengan-proteksi-kode-dan-kontrol-layanan
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!