patrick.1729
patrick.1729

Reputation: 4402

Huge difference in build size of Electron Forge and Electron builder

I have just started learning Electron from the official Quick Start guide. At the end of the guide, they've recommended to use Electron Forge as the tool to create the distributable package. Another tool for the same purpose is Electron Builder.

I've used the latter before and out of curiosity I created the quick start app build with both the tools. To my surprise, there is a huge difference between the dmg builds that were created for the same app on MacOS:

I understand the Electron builds are fairly large in size due to the shipment of Chromium and Node along with the package but this significant difference (~134.2 MB) between the builds of a quick start app is quite not clear to me.

package.json:

{
    "name": "my-electron-app",
    "version": "1.0.0",
    "description": "Hello World",
    "main": "main.js",
    "scripts": {
        "test": "test",
        "start": "electron-forge start",
        "package": "electron-forge package",
        "make": "electron-forge make"
    },
    "license": "MIT",
    "devDependencies": {
        "@electron-forge/cli": "^6.0.0-beta.57",
        "@electron-forge/maker-deb": "^6.0.0-beta.57",
        "@electron-forge/maker-rpm": "^6.0.0-beta.57",
        "@electron-forge/maker-squirrel": "^6.0.0-beta.57",
        "@electron-forge/maker-zip": "^6.0.0-beta.57",
        "electron": "^13.1.6",
        "electron-builder": "^22.11.7",
        "electron-log": "^4.3.5",
        "electron-reloader": "^1.2.1"
    },
    "dependencies": {
        "electron-squirrel-startup": "^1.0.0"
    },
    "config": {
        "forge": {
            "packagerConfig": {},
            "makers": [
                {
                    "name": "@electron-forge/maker-squirrel",
                    "config": {
                        "name": "my_electron_app"
                    }
                },
                {
                    "name": "@electron-forge/maker-zip",
                    "platforms": [
                        "darwin"
                    ]
                },
                {
                    "name": "@electron-forge/maker-deb",
                    "config": {}
                },
                {
                    "name": "@electron-forge/maker-rpm",
                    "config": {}
                }
            ]
        }
    }
}

I need help with the following questions:

  1. Why there is a huge difference for a simple quick starter app?
  2. Is there any way or standard practice with which we could reduce the final build size in Electron (besides npm prune, deleting node_modules and then creation of build as it had no effect)?

Upvotes: 4

Views: 5077

Answers (1)

georch
georch

Reputation: 1444

I had the same problem today, a simple app became a 1GB package.

Both electron-forge and electron-builder bundle all files inside your project directory by default. This is particularly much if some of your build tools generate temporary files in your project directories (e.g. caches). The difference you see is likely due to different default exclude rules.

Here's what you can do to get it smaller for both electron-forge and electron-builder:

Finding out why the package is so big

In both cases, you can inspect the generated .asar file (under /resources in your published, unpackaged directory) like this:

npx asar extract insert/path/here/resources/app.asar ./asar-extracted

You can then have a look at the individual files. For example, you can run du -h ./asar-extracted (under Linux/Unix) to find out what's taking so much space. For a better/graphical experience, I can recommend qdirstat (Linux) or windirstat (Windows). Or just use your file explorer.

You will probably see two things: a. node_modules is quite big. b. all the other files from your project directory are included

Move dependencies to devDependencies

Both tools will automatically remove all dependencies that are not in the dependencies section of package.json (or depend on them). This means that you can put any dependency that isn't required in the electron app itself into devDependencies.

If you are using a bundler like e.g. webpack, vite or parcel, then it's likely going to bundle all dependencies required from your HTML into the dist directory, so that you won't need them in node_modules in the published application. You can put all of those dependencies into devDependencies. For example, react is probably just required for the bundle, so you can put it into devDependencies. Only the dependencies needed in your main process code need to stay. For my use case, I was able to move almost all the dependencies.

You can also decide to bundle your main process code as well, removing the need for any non-dev dependency.

Exclude other files

To remove the other files that are in your project folder and thus included, you need to adjust the configuration. Let's assume that the (bundled/built) code that you want to bundle lies in a folder called dist-electron for the following.

electron-forge

For electron-forge, this is done via regexes. For example, you can put something like this in your forge.config.js:

module.exports = {
  packagerConfig: {
    ignore: [
      // exclude everything but package.json, node_modules and dist-electron
      /(?!package\.json|node_modules|dist-electron)/,
    ],
    // ...
  },
  // ...
};

The docs are a bit hidden, you can't find them when searching in the forge docs, since they come from a different package. You can find them here (referenced here in the forge docs).

Once you've found the right docs, you'll see this note in bold:

Please note that glob patterns will not work

(Probably because that's the first thing that everyone tries.)

electron-builder

For electron-builder, you could e.g. put this into your package.json:

    "build": {
        "files": {
            "filter": [
                "dist-electron",
            ]
        }
    }

This has pretty much the same effect as the electron-forge configuration above. The required files from node_modules as well as package.json are included by default (docs).

You can also use glob patterns like *.bin or !exclude-this (docs).


Tbh after testing both for the first time today, I would not recommend electron-forge right now. The built-in scaffolding may be nice, but the docs are really, really limited. The docs for electron-builder are way better, and they also list quite a few third-party templates here to get started. The fact that the Electron docs frame Forge as the "official" solution is IMO not ideal when the project seems much less mature than electron-builder.

Upvotes: 2

Related Questions