18
Electron Adventures: Episode 3: What Can Backend Code Even Do?
Let's do something that frontend code can't do on its own - run shell commands.
Electron on the backend is basically node process, with some extras for communicating with the browser.
Now it would much prefer you to use complicated async system with proper error handling and so on, but we don't need this complexity - we'll just use child_process.execSync
to run a command and capture its output.
We need to do two small things with the result. First we need to convert Buffer
into String
- this isn't done automatically, as the output could be some binary like an image, not a valid UTF-8 String. And then we'll trim extra newline.
let child_process = require("child_process")
let runCommand = (command) => {
return child_process.execSync(command).toString().trim()
}
Let's run a bunch of random commands to get system information
let sysInfo = {
os: runCommand("uname -s"),
cpu: runCommand("uname -m"),
hostname: runCommand("hostname -s"),
ip: runCommand("ipconfig getifaddr en0"),
}
We can now ship this information to the frontend. There are many more complex ways, and we'll absolutely get there, but for now, let's jut use the simplest one and pass a query string.
Weirdly Javascript still doesn't have a way to turn an Object
into a query string, so we'll need to roll our own!
let toQueryString = (obj) => {
let q = []
for (let key in obj) {
q.push(`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
}
return q.join("&")
}
We used loadFile
function before, but that doesn't have any easy way of passing an query string. But we can do a little trick, and use loadURL
with file:
protocol instead.
let { app, BrowserWindow } = require("electron")
function createWindow() {
let win = new BrowserWindow({})
win.maximize()
win.loadURL(`file:${__dirname}/index.html?${toQueryString(sysInfo)}`)
}
app.on("ready", createWindow)
app.on("window-all-closed", () => {
app.quit()
})
Javascript has a way to parse a query string, but it's not very convenient. But let's give it a go the hard way with just browser APIs:
let data = new URLSearchParams(document.location.search)
let info = document.querySelector("#info")
for (const [key, value] of data) {
let p = document.createElement("p")
p.append(`${key} = ${value}`)
info.append(p)
}
We absolutely do not want to be writing bigger apps this way of course, so we'll get to using libraries soon.
For now let's just add this simple HTML, and we have a simple app:
<!DOCTYPE html>
<html>
<body>
<h1>System information!</h1>
<div id="info"></div>
<script src="app.js"></script>
</body>
</html>
And here's what we got:
See you in the next episode!
18