Creating Electron Installer for Both Mac Os and Windows

So you have created up a great looking Electron-based app. Now you want to create an installer for it, There is a lot of articles that can help you, but in this, I am going to share my story of how I did it, and it is also for the people who are using electron and react together.

So how we do it, 2 steps for each platform, and I am going to share my journey of windows and mac platform. First is step is making a package, and the second step will be making of an Installer.

1️⃣First Step

Creating a package is pretty simple, but if you have a complex project will a lot of modules, you need to configure this manually.

First thing you need to move all your project-related node_modules to dev dependency, you heard me right, You need to move all your node_modules to dev Dependency except those are being used in your node_proccess. So if you have used axios let's say, you have to leave it on dependencies section inside node_modules. WHY? The reason is when you run electron-packager, it will going to move all your source code, including node_modules’ dependencies inside of the packaged app, which will dramatically increase the size of the app. So only leave dependencies that are using inside of main.js and move others as devDepencies.

Then create an empty file name it electron-packager and copy this into it.

var packager = require("electron-packager");
var options = {
arch: "x64",
platform: process.platform,// this will automatically select darwin if darwin or win32 if win32
dir: "./", // which directory to pack
"app-copyright": "",// fill this
"app-version": "0.0.1",
asar: true, // this will archive your source code.
icon: "./logo.ico",
name: "", // fill this
ignore: [
// list every thing that need to be ignore, so reference every single director and leave the build of the app and the files that are being used in the node module.
out: "./build/releases",
overwrite: true, // will overwrite whatever it might have written before.
prune: true,
version: "0.0.1",
"version-string": {
CompanyName: "",// fill this
"" /*This is what display windows on task manager, shortcut and process*/,
OriginalFilename: "",// fill this
ProductName: "",// fill this
InternalName: "",// fill this
packager(options, function done_callback(err, appPaths) {

The above code is self-explanatory, and after pasting the above code, you need to run node electron in the terminal. You will get a for a folder called to build, and inside of it, you will have the release folder with your app packaged inside.

You need to make sure to ignore all the files that you don't want to expose, so if for example if I am using static react site, I need to ignore the src folder, otherwise my code will be exposed to the world, and I don't want that.

2️⃣Second Step

for Windows 👇

electron-installer-windows --src pathto/packaged_app_folder/ --icon logo.ico --dest build/releases/

for Osx 👇

electron-installer-dmg ./path_to_packaged_app_folder/ name_of_the_installer --overwrite

You can now run any of the above commands in the terminal, and it creates you an installer for the app.


function handleSquirrelEvent() {
if (process.argv.length === 1) {
return false;
const ChildProcess = require("child_process");
const path = require("path");
const appFolder = path.resolve(process.execPath, "..");
const rootAtomFolder = path.resolve(appFolder, "..");
const updateDotExe = path.resolve(path.join(rootAtomFolder, "Update.exe"));
const exeName = path.basename(process.execPath);
const spawn = function (command, args) {
let spawnedProcess, error;
try {
spawnedProcess = ChildProcess.spawn(command, args, { detached: true });
} catch (error) {}
return spawnedProcess;
const spawnUpdate = function (args) {
return spawn(updateDotExe, args);
const squirrelEvent = process.argv[1];
switch (squirrelEvent) {
case "--squirrel-install":
case "--squirrel-updated":
// Optionally do things such as:
// - Add your .exe to the PATH
// - Write to the registry for things like file associations and
// explorer context menus
// Install desktop and start menu shortcuts
spawnUpdate(["--createShortcut", exeName]);
setTimeout(app.quit, 1000);
return true;
case "--squirrel-uninstall":
// Undo anything you did in the --squirrel-install and
// --squirrel-updated handlers
// Remove desktop and start menu shortcuts
spawnUpdate(["--removeShortcut", exeName]);
setTimeout(app.quit, 1000);
return true;
case "--squirrel-obsolete":
// This is called on the outgoing version of your app before
// we update to the new version - it's the opposite of
// --squirrel-updated
return true;
if (handleSquirrelEvent()) {
// squirrel event handled and app will exit in 1000ms, so don't do anything else

This will do the rest for you.

🔴 There will be one more problem that you are going to face; it will be the FILE protocol path within your app. After packing your app will not be in a compressed file because of asar. Here is an example of how I fix this problem.

const preloadLink = () => {
return isDev
? process.platform == "darwin"
? "file:///" + path.resolve(`./src/utils/${preload}.js`)
: "" + path.resolve(`./src/utils/${preload}.js`)
: window.location.href.split("/").slice(0, -2).join("/") +

Anyways, that is it for today. 🏃‍♀️

Thank you for reading this short article. I hope you found it useful.

LinkedIn 🔗
Github 🔗

A Resident of the Javascript Rockstar world. The Rockstar himself is actively exploring JOB Opportunities in Germany and Canada.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store