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.
Install and run import
$ 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 toindex.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:
{
"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 independencies
notdevDependencies
, 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
:
{
"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
:
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:
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.
Top comments (1)
After a few bumps and tweaks, I finally managed to package my simple Cookie Clicker game into a standalone app using Electron Forge! The initial setup wasn't smooth – with some issues like missing properties in package.json and dependencies in the wrong place – but after fixing those, it all started coming together. Moved the source code to src, added some boilerplate to handle Windows shortcuts, and voilà! Now my app is ready to run. This whole journey reminds me of why I enjoy building these little projects, like my site cookieclickerunblocked.us/ where I explore similar simple gaming setups. Excited to take it further in the next episode by building a more complex SPA!