Kees
Kees

Reputation: 373

How to package an Electron app into a single executable?

Using electron-packager I can create a 'packaged' version of my JavaScript application for various architectures and platforms. However, it does not package each build as a single binary which I can distribute.

When looking for alternatives I found out about EncloseJs, but it is not free (and I prefer a free solution).

Another one I found was electron-boilerplate, which only creates a *.deb, *.app or a Windows installer, but not a single executable which will run the program.

Is it possible to use Electron to create a single executable file?

Upvotes: 27

Views: 53033

Answers (6)

gregnr
gregnr

Reputation: 1272

For those using electron-forge, we've built a Maker plugin that builds a portable Windows .exe file using electron-builder's portable target under the hood:

https://github.com/rabbit-hole-syndrome/electron-forge-maker-portable

Upvotes: 4

user2959760
user2959760

Reputation: 516

electron single .exe:

electron-builder --win portable

It generates a single .exe !!!

And you don't need to touch package.json.

More info doc


If electron-builder show some error:

Cannot find module 'fs/promises' Electron JS

Downgrade Electron Builder using: "electron-builder": "22.10.5" or upgrade NodeJS to 14+ More info here.

Upvotes: 9

Kiran Maniya
Kiran Maniya

Reputation: 9009

Try using electron-builder -p --win. it will build up the production-ready .exe. I did it with electron-builder@21.2.0

for the publishable build, you'll need the publishing provider in your package.json file, consider the given example.

"build": {
    "appId": "com.trinityinfosystem.electron.exchange.stream",
    "productName": "Accurate",
    "copyright": "Copyright © 2018 Trinity InfoSystem",
    "mac": {
      "category": "public.app-category.utilities",
      "icon": "assets/icon.icns",
      "target": [
        "zip",
        "dmg"
      ],
      "publish": [
        "github"
      ]
    },
    "win": {
      "publisherName": "Trinity InfoSystem",
      "publish": [
        "github"
      ],
      "target": [
        "nsis"
      ]
    },
    "linux": {
      "target": [
        "AppImage",
        "tar.gz"
      ]
    },
    "dmg": {
      "background": "assets/background.png",
      "icon": "assets/icon.icns",
      "title": "Accurate Installer"
    },
    "nsis": {
      "oneClick": false,
      "perMachine": false,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "assets/icon.ico",
      "installerSidebar": "assets/sidebar.bmp",
      "uninstallerSidebar": "assets/sidebar.bmp",
      "license": "assets/agreement.html",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true
    },
    "publish": [
      {
        "provider": "github",
        "owner": "vkiranmaniya",
        "repo": "accurate",
        "vPrefixedTagName": true,
        "private": true,
        "releaseType": "draft"
      }
    ]
  },

Add the given pulishing config to your package.json as root proprty. You will need the Github personal access token (here is the Doc) to be exported while running a build.

You can export the token as env variable from main.js as given,

process.env.GH_TOKEN = 'YOUR_PERSONAL_ACCESS_TOKEN_HERE';

If you want to setup AutoUpdate using GitHub, you can use the given module and call checkForUpdates() method from main.js

const electron = require("electron");
const updater = require("electron-updater");
const autoUpdater = updater.autoUpdater;

autoUpdater.on('checking-for-update', function () {
    sendStatusToWindow('Checking for update...');
});

autoUpdater.on('update-available', function (info) {
    sendStatusToWindow('Update available.');
});

autoUpdater.on('update-not-available', function (info) {
    sendStatusToWindow('Update not available.');
});

autoUpdater.on('error', function (err) {
    sendStatusToWindow('Error in auto-updater.');
});

autoUpdater.on('download-progress', function (progressObj) {
    let log_message = "Download speed: " + progressObj.bytesPerSecond;
    log_message = log_message + ' - Downloaded ' + parseInt(progressObj.percent) + '%';
    log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
    sendStatusToWindow(log_message);
});

autoUpdater.on('update-downloaded', function (info) {
    sendStatusToWindow('Update downloaded; will install in 1 seconds');
});

autoUpdater.on('update-downloaded', function (info) {
    setTimeout(function () {
        autoUpdater.quitAndInstall();
    }, 1000);
});

function checkForUpdates(){
    const data = {
        'provider': 'github',
        'owner':    'vkiranmaniya',
        'repo':     'exchange',
        'token':    'YOUR_PERSONAL_TOKEN_HERE'
      };
    autoUpdater.setFeedURL(data);
    autoUpdater.checkForUpdates();
}

function sendStatusToWindow(message) {
    console.log(message);
}

module.exports = {
    checkForUpdates,
}

Now you can run the command electron-build -p --win to build an auto updatable standalone .exe file. Use --mac or --linux to target specific platform for build.

Upvotes: 18

Polar
Polar

Reputation: 3547

I'm not sure if there is a newer solution but you can use BoxedApp, You had to buy it though but you can search for a free version.

You can also use WinRAR, your project will pack into single exe by creating SFX archive. Here is a video on How To Make Portable Application using WinRAR.

CONS: launching application will takes longer.

NOTE: You have to pack your project first before using any of the method above.

PS: Tested on Windows only.

Hope this help.

Upvotes: 2

GorvGoyl
GorvGoyl

Reputation: 49580

yup, it's (now) possible. Choose any of the modules to generate single exe file: electron-builder, electron-forge or windows-installer .

Upvotes: 12

inukshuk
inukshuk

Reputation: 1457

Not really, but that's OK.

I doubt that there are many desktop apps which consist solely of an executable. Typically you will have lots of resource files. Electron is just the same: it comes with a 'single executable' file that starts Electron and many additional files. When you use electron-packager you get a single executable that starts your app but it is bundled with lots of resource files (like your Javascript code). I suppose you could try and use some kind of bin packer to bundle everything into a single binary, but why do you want to do that? Most apps consist of many files and folders and have no issue with it.

Upvotes: 1

Related Questions