Search code examples
angularnpmelectronelectron-builderasar

electron-builder MSI installer asar file too large


I have an Angular app for which I need to create an MSI installer. I have successfully created an electron app (npm run electron), but when I try to create the installer I get this error:

error LGHT0263 : 'C:...\release\win-unpacked\resources\app.asar' is too large, file size must be less than 2147483648.

I ran the commands in this order:

  1. npm run electron --> to run the electron app itself to see if it works (I closed the app before doing the next steps)
  2. npm run tsc
  3. npm run step2
  4. npm run electron:build

I assume I am including too many files in electron-builder.json, but I am not sure what I can remove and what is required for the app to run since this is my first time using electron and electron-builder.

When I set "asar": false in electron-builder.json, the MSI installer is created, but I get the warning asar usage is disabled — this is strongly not recommended, it takes forever (i.e. 30-ish minutes) to build and the MSI packet is almost 1.5 GB in size.

Does anybody know how I can reduce the asar size?

This is my project structure:

|- dist
|- electron
   |- main.ts
   |- package.json
|- node_modules
|- release
|- src
   |- all angular source code
|- angular.json
|- electron-builder.json
|- package.json
|- tsconfig.json
|- tsconfig.serve.json

Scripts in package.json:

"scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "electron": "ng build --configuration electron && electron .",
    "tsc": "tsc -p tsconfig.serve.json",
    "step2": "ng build --base-href ./ --configuration electron",
    "electron:build": "electron-builder build --publish=never"
  }

electron-builder.json:

{"asar": true,
  "directories": {
    "output": "release/"
  },
  "files": [
    {
      "from": "dist",
      "filter": ["**/*"]
    },
    {
      "from": "electron",
      "filter": ["**/*"]
    },
    {
      "from": "src",
      "filter": ["**/*"]
    },
    "!**/*.ts",
    "!*.map",
    "!package.json",
    "!package-lock.json",
    "!node_modules/**",
    "!.angular/**",
    "!.vscode/**",
    "!cypress/**",
    "!release/**"
  ],
  "win": {
    "icon": "offline-test.ico",
    "target": [
      "msi"
    ]
  }
}

tsconfig.serve.json:

{
  "compilerOptions": {
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "target": "es2015",
    "types": [
      "node"
    ],
    "lib": [
      "es2017",
      "es2016",
      "es2015",
      "dom"
    ]
  },
  "files": [
    "electron/main.ts"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

I looked at this question, but I think I am excluding the directory where the MSI file is, so I'm not sure what else I can exclude.


Solution

  • I never used Angular, so I won't be able to give you full working configuration, but whatever library is used, usually when packaging for Electron you first want to bundle your files, and then only pack these files.

    Roughly, you should:

    • Bundle your renderer, main and preload (if you have one) files into a single output folder
    • Make sure you use a different output folder for bundling and for packaging (to prevent conflicts)
    • Tell the builder to package only the bundle output folder
    • Add modules that can't be bundled manually (if you have any)

    Once you have everything neatly inside your output folder (I gathered that for Angular the default is dist/[project-name]), you can then configure electron-builder accordingly:

    {
      "extraMetadata": {
        // This will change the `main` field of your `package.json`,
        // so electron-builder will use the file made for prod.
        "main": "dist/[project-name]/[path-to-bundled-main-file]"
      },
      "files": [
        "./dist/[project-name]/**/*"
      ]
    }
    

    For native module that can't be bundled, you can use the asarUnpack option to include them in the package.

    Also, if I'm not wrong, Angular CLI uses webpack to bundle, so you will probably need to use the target electron-main and electron-preload to bundle your Electron files so everything works correctly.