Shipping executables with your Electron app

Shivek Khurana
3 min readFeb 18, 2019

--

Photo by Nicole Wolf on Unsplash

My app, HTTPSLocalhost (The fastest, most secure way to handle local SSL), needed a local proxy server that listens to port 443 and redirects the traffic to a pre-configured port.

I wrote this server using Node’s http package and configured it to run using the command line. It was as simple as firing a shell and running the following command:

$ node proxyServer.js `/path/to/ssl/certs` `[{proxy: 'config1'}, {proxy: 'config2'}]`

On my local setup, I just had to exec the command and it worked. But this was an Electron app and shipping this as it is meant three things:

  1. The source of proxyServer would be visible to everyone using the app
  2. I was assuming that my script was capable of running on all versions of Node (which is very bold)
  3. I had to bundle node_modules folder with the app (which would drastically increase the build size)

So I started looking for other ways to go around this issue.

Converting Node apps to standalone executables with Pkg

For people who are not familiar with the JS ecosystem, Zeit is the company behind Next.js and Now.sh.

Pkg by Zeit is a tool that bundles a Node app into a cross-platform executable that can run without a Node installation. Mind-blown!

And packaging your app was as simple as:

$ pkg path/to/index.js

When I first saw this, I was a little skeptic. I have seen tools like these before and almost none of them work as advertised.

Pkg, however, exceeded my expectations. Not only it worked, but it was also able to produce a bundle of the proxyServer.js that worked without a Node installation and was only 49mb in size (including dependencies).

This is a serious contender for deploying Node web apps. Will surely consider this the next time I have a need to do so. It’s like jar for Node.

Packaging the executable with electron-builder

After having built the executable and putting it insider build/executables directory, I had to update my package.json to include this in the electron package output. This required me to add an extraResources key to the build configuration:

"build": {
...
"extraResources": [
"build/**/*"
]
}

The above copies everything inside build to AppPath/Contents/Resources/build . The path to Resources folder is available as process.resourcesPath variable for MacOS builds. This might vary on other OSes.

I packaged my proxyServer, added yarn scripts to automate the task and hoped everything would work in the first go. Guess what, it didn’t.

Handling native addons (.node files)

My setup worked fine in dev mode but threw an error when built. The error basically meant that the system was looking for a .node file and wasn’t able to find it.

After 3 months of research and giving up on the problem many times, I found this issue on Github: https://github.com/zeit/pkg/issues/343

And then I realized that the project Readme had this issue highlighted already. The solution was simple. Just put the .node file along with the executable and it would work.

# Excerpt from zeit/pkg Readme
Native addons (.node files) use is supported, but packaging .node files inside the executable is not resolved yet. You have to deploy native addons used by your project to the same directory as the executable.

After fixing this issue, the packaged app worked just fine. You can try it for yourself.

Hi, if you liked this article and want to stay updated, follow me on: Medium, Github or Twitter

You might also like:

Ta

--

--

Shivek Khurana
Shivek Khurana

Written by Shivek Khurana

🏋🏻‍♂️ Founder — Building Meta Blocks — The NFT evolution protocol | 🔫 Talks about 📜 code, 🏛 crypto, 🕸 web3 and 🪖 ed-tech | 👼🏼 Angel Investor | W

Responses (1)