Electron Adventures: Episode 78: Cookie Clicker Game Packaging
Tags: javascript, electron
Published: 2021-10-08 16:44:25

In previous episode we created a simple static Cookie Clicker game app. Let's now package it into a standalone app.

There are a few different packagers for Electron. In this episode we'll try [Electron Forge](https://www.electronforge.io/).

### Install and run import

```shell
$ npm install --save-dev @electron-forge/cli
$ npx electron-forge import
```

Electron Forge comes with an import tool that tries to import an existing app.

We ran into some problems right away:

* `Please set the "version" in your application's package.json` - I guess that would be useful for naming the package
* `Error: Unable to find all properties in parent package.json files. Missing props: ["productName","name"]` - and same here
* `Error: packageJSON.main must be set to a valid entry point for your Electron app` - Electron defaults to `index.js` if you don't specify it, but Electron Forge need it spelled out explicitly

So reset the process, fix those issues so `package.json` looks like below, and try again:

```javascript
{
  "name": "episode-78-cookie-clicker-game-package",
  "version": 0.78,
  "main": "index.js",
  "devDependencies": {
    "electron": "^15.1.1",
    "jquery": "^3.6.0"
  },
  "scripts": {
    "start": "electron ."
  }
}
```

That actually built the package, but it still didn't work.

The next few issues I needed to fix:

* I accidentally put version as `0.78` not `"0.78"` and that led to some extremely baffling and completely ungooglable errors
* `jquery` must be in `dependencies` not `devDependencies`, or it won't be bundled. While developing it makes no difference, but it decides what's going to get packaged and what won't.
* I needed to do some tweaks to `index.js` to use relative path. I also included some boilerplate that supposedly fixes Windows shortcuts, as examples had it.

So after a few iterations between myself and the importer I got to this `package.json`:

```javascript
{
  "name": "episode-78-cookie-clicker-game-package",
  "version": "0.78",
  "main": "src/index.js",
  "devDependencies": {
    "@electron-forge/cli": "^6.0.0-beta.61",
    "@electron-forge/maker-deb": "^6.0.0-beta.61",
    "@electron-forge/maker-rpm": "^6.0.0-beta.61",
    "@electron-forge/maker-squirrel": "^6.0.0-beta.61",
    "@electron-forge/maker-zip": "^6.0.0-beta.61",
    "electron": "^15.1.1"
  },
  "scripts": {
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make"
  },
  "dependencies": {
    "electron-squirrel-startup": "^1.0.0",
    "jquery": "^3.6.0"
  },
  "config": {
    "forge": {
      "packagerConfig": {},
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "config": {
            "name": "episode_78_cookie_clicker_game_package"
          }
        },
        {
          "name": "@electron-forge/maker-zip",
          "platforms": [
            "darwin"
          ]
        },
        {
          "name": "@electron-forge/maker-deb",
          "config": {}
        },
        {
          "name": "@electron-forge/maker-rpm",
          "config": {}
        }
      ]
    }
  }
}
```

I also moved the source code to `src` folder and adjusted imports accordingly.

Here's final `src/index.js`:

```javascript
let { app, BrowserWindow } = require("electron")

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require("electron-squirrel-startup")) {
  app.quit()
}

function createWindow() {
  let win = new BrowserWindow({
    webPreferences: {
      preload: `${__dirname}/preload.js`,
    },
  })
  win.loadFile(`${__dirname}/index.html`)
}

app.on("ready", createWindow)

app.on("window-all-closed", () => {
  app.quit()
})
```

The actual app is just as before.

### Results

Here's the results:

![Episode 78 Screenshot A](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axhcfobg123sb2sw057t.png)

![Episode 78 Screenshot B](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55es0czqnifksulgphhf.png)

The whole process was very finicky and with very poor error feedback, but in the end it wasn't too bad. In the next episode we'll setup some more complex SPA app, then we'll try to package that.

As usual, [all the code for the episode is here](https://github.com/taw/electron-adventures/tree/master/episode-78-cookie-clicker-game-package).