What is electron ?
Electron is a JavaScript framework that enables you to create a desktop applications with simple JavaScript, HTML, and CSS.
Can you share some practical use cases where electron fit for it?
1) You want to create a new desktop application (single code base) which needs to run on macOS, Windows, or Linux, or distributed
via the Mac App Store or the Microsoft Store
2) You have an existing web application and want to have a desktop flavour of the same and need to drive both Web & Desktop versions
Share some common electron application in day to day use?
1) Skype (initially it was developed using the high level language 'Delphi')
2) Visual Studio Code
3) WhatsApp
4) Slack
Is electron framework an open source?
Yes, its an open source maintained by GitHub
List some important features available in electron framework?
- Automatic updates of deployed window application (similar to smart deploy in Microsoft)
- Native menus & notifications available which can be used to create a native windows app feature
- Application installer can be created to easily ship the developed application
- Debugging & Profiling tools are available
How electron framework works ?
Simple, it works on following combination
Chromium (display web content developed in HTML, CSS, JS)
+
Node JS ( to work with local file system of an operating system. You can see this feature extends the web app as desktop app)
+
Custom APIs (to invoke OS native functions. Example, OS module (home directory, user info etc.,) & Net module (create socket, listen on port) )
How do you build a electron desktop application using existing WebApp (ReactJS) + Node JS ?
Step 1: build React JS application (npm run build)
Step 2: Keep the above build binaries of "React JS" inside "NodeJS" application
Step 3: Introduce a electron file (.js) inside same "NodeJS" application and launch the "index.html" in the electron browser window
Will share the detailed step in another article
How do we protect the Node JS code being exposed while deploy on PROD server?
You can archive the code as .asar file which protects the source code of the app from being exposed to other users
How do we convert Node JS code to .asar file?
There are two ways
1) Manually archive the folder using asar command
asar pack app app.asar
2) Integrate the asar feature inside electron application in configuration level (package.json)
"build": {
"appId": "docmgmt",
"win": {
"target": [
"nsis"
],
"requestedExecutionLevel": "requireAdministrator",
"asar": false
}
Does .asar file is safe?
Just it makes one layer of difficulty in reading the code but it can be extract back as code from archive using below command
npx asar extract app.asar destfolder (extract the whole archive)
npx asar extract-file app.asar main.js (extract a single file)
What is an alternative for method for archive code (.asar)?
Obfuscation => It is a process which converts the JavaScript source code into obfuscated and completely unreadable form, preventing it from analyzing and theft.
Can you share a famous obfuscation tool for Java Script source code ?
Personally I feel https://javascriptobfuscator.com/ is simple and effective way of obfuscating JS code.
Note: They provide free version with obfuscation level 1 (little complex) and same licensed version make the obfuscation using more complex parameter
Can you show a complete example of electron source code of packaging ReactJS + NodeJS + Electron application ?
const electron = require('electron');
const {ipcMain} = require('electron');
const spawn = require('child_process').spawn;
const app = electron.app;
const BrowserWindow = electron.BrowserWindow
const url = require('url')
const path = require('path')
const iconPath = path.join(__dirname, "/public/build/", "appicon.ico");
const config = require("./src/config");
const startup = require("./nodejsapp");
let mainWindow, splashWindow
function createSplashWindow(){
splashWindow = new BrowserWindow({width:800,height:500, frame:false, loadFile:'splashscreen.html'}) ;
splashWindow.loadFile(path.resolve('file:\\',__dirname,'splash-screen','splashscreen.html'));
splashWindow.show();
splashWindow.focus();
}
ipcMain.on("executeApp",(event,data)=>{
executeApp(data);
event.reply("Acknowledge","Triggered requested application");
})
function executeApp(data){
var appPath = "C:\Program Files\Notepad++\notepad++.exe"
const ls = spawn(appPath,["C:\Users\cmraja\Desktop\testfile.txt"]);
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
console.log('notepad started at proceessID');
}
async function createWindow() {
mainWindow = new BrowserWindow( //C# WinForm, WebBrowser control
{
icon: iconPath,
width: 1200,
height: 600,
show: false,
webPreferences: {
nativeWindowOpen: true,
nodeIntegration: true //,
// contextIsolation:false
},
});
createSplashWindow();
await triggerSerivceApp();
mainWindow.once('ready-to-show',()=>{
setTimeout(() => {
//splashWindow.close();
mainWindow.show();
}, 5000);
})
mainWindow.webContents.once('dom-ready', () => {
mainWindow.loadURL('http://localhost:3002'); //C# WinForm, webBrowserCtrl.Navigate("https://localhost:3002");
});
mainWindow.on('closed', () => {
mainWindow = null
})
}
async function triggerSerivceApp() {
await startup; //Trigger NodeJS application which in turn lauch React JS application on port 3002 and it can be accessed thru URL "http://localhost:3002"
// mainWindow.loadURL('http://localhost:3002'); //To load a URL directly into electron widow
mainWindow.loadURL(url.format({ //To load a HTML file into electron widow
pathname:path.join(__dirname,'build','index.html'),
protocol:'file',
slashes:true}));
}
app.on('ready',createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') { //as per MacOS convention, it will run as background task thus closing explicitly on Win & Linux platform
app.quit()
}
})
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
})
Is there difference in using "__dirname" and "./" in Node.js ?
Yes, and it some time become very tedious to debug the issue. It is important to understand when you are working with electron application with archive (.asar) format during deployment
__dirname => returns the directory of JS file which is being executed
./ => returns the directory where the application is triggered
Example,
printDirectory.js (resides under D:/tekkieshaper/test folder)
var path = require("path");
// Retrieve the current directory
console.log("__dirname : ", __dirname);
console.log("process.cwd() : ", process.cwd());
console.log("./ : ", path.resolve("./"));
console.log("file name : ", __filename);
Output:
d:/tekkieshaper> node test/printDirectory.js
__dirname : d:\tekkieshaper\test
process.cwd() : d:\tekkieshaper
./ : d:\tekkieshaper
file name : d:\tekkieshaper\test\printDirecotry.js
How to install Electron JS in Ubuntu ?
sudo npm install -g electron
sudo npm install -g electron --unsafe-perm=true --allow-root (if you get permission denied error)
How can we archive (zip) the Electron & Node JS files and what is the use?
Archive file formats helps to create a single file by merging multiple files and directories
One best tool is ".asar" tool which provides random access support. i.e., you can extract a specific file from the archive one
How to setup the asar utility, archive and extract files back?
1) Install asar tool and this tool works in Node.JS version 10.X and above
npm install -g asar
Note: use of npx is to avoid to the above installation of asar tool globally with npm
2) Archive a files under a folder "asartest" and name the archive file as "app.asar"
npx asar pack asartest app.asar
3) How to list out the files inside an archive (ex: app.asar)
npx list app.asar
4) Extract the files back from "app.asar" to a folder called "out"
npx asar extract app.asar out (all files extracted back to the folder "out")
npx asar extract file2.txt app.asar out (it extracts a file2.txt alone and place it in folder "out")