Skip to main content
electron-builder packages your application code and resources into distributable formats. Understanding how files are organized and what gets included is crucial for optimizing your app’s size and performance.

Default File Inclusion

By default, electron-builder includes:
  • Your application code (from the app directory)
  • node_modules dependencies
  • package.json
  • All required runtime files
The default behavior automatically excludes development dependencies, test files, and common non-runtime files.

ASAR Archives

What is ASAR?

ASAR (Atom Shell Archive) is a simple archive format that concatenates files into a single file. Electron can read files from ASAR archives without unpacking them, which provides:
  • Faster loading: Single file reads are faster than many small file reads
  • Reduced file count: Improves performance on Windows
  • Basic obfuscation: Source code is not immediately visible (but not encrypted)

Default ASAR Configuration

By default, your application code is packaged into app.asar:
package.json
{
  "build": {
    "asar": true
  }
}

ASAR Integrity Validation

electron-builder supports ASAR integrity validation to prevent tampering:
package.json
{
  "build": {
    "electronFuses": {
      "enableEmbeddedAsarIntegrityValidation": true,
      "onlyLoadAppFromAsar": true
    }
  }
}
ASAR integrity checking is supported on:
  • macOS as of Electron 16.0.0+
  • Windows as of Electron 30.0.0+
When enabling onlyLoadAppFromAsar, Electron will only load code from app.asar, not from unpacked app directories. Combine this with integrity validation for maximum security.

Unpacking Files from ASAR

Some files need to be unpacked from ASAR:
  • Native Node.js addons (.node files)
  • Files accessed by external processes
  • Files that need to be executable
package.json
{
  "build": {
    "asar": true,
    "asarUnpack": [
      "**/node_modules/sharp/**/*",
      "**/node_modules/sqlite3/**/*",
      "**/node_modules/**/*.node"
    ]
  }
}
electron-builder automatically unpacks .node files by default. You only need to explicitly specify asarUnpack for special cases.

Disabling ASAR

For development or specific use cases, you can disable ASAR:
{
  "build": {
    "asar": false
  }
}
Disabling ASAR increases the number of files in your package, which can slow down application startup, especially on Windows.

File Configuration Options

files

Specifies which files to include in the application:
package.json
{
  "build": {
    "files": [
      "dist/**/*",
      "node_modules/**/*",
      "package.json",
      "!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}",
      "!**/node_modules/.bin",
      "!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}",
      "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore}"
    ]
  }
}
See File Patterns for detailed information on glob pattern syntax.

extraResources

Files to copy to the app’s resources directory (outside ASAR):
package.json
{
  "build": {
    "extraResources": [
      {
        "from": "assets/",
        "to": ".",
        "filter": ["**/*"]
      },
      "LICENSE.txt",
      "bin/helper"
    ]
  }
}
Location in packaged app:
  • macOS: Contents/Resources/
  • Windows: resources/
  • Linux: resources/
Accessing in code:
import path from 'path'
import { app } from 'electron'

const resourcesPath = process.resourcesPath
const assetPath = path.join(resourcesPath, 'assets', 'icon.png')

extraFiles

Files to copy to the app’s output directory (outside ASAR and resources):
package.json
{
  "build": {
    "extraFiles": [
      {
        "from": "bin/${os}/",
        "to": ".",
        "filter": ["**/*"]
      },
      "README.md"
    ]
  }
}
Location in packaged app:
  • macOS: Contents/ (app contents root)
  • Windows: App directory root
  • Linux: App directory root

FileSet Configuration

Both extraResources and extraFiles support FileSet configuration:
{
  "build": {
    "extraResources": [
      {
        "from": "build/assets/",
        "to": "assets",
        "filter": [
          "**/*",
          "!**/*.map"
        ]
      }
    ]
  }
}
FileSet interface:
interface FileSet {
  /**
   * The source path relative to the project directory.
   */
  from?: string
  
  /**
   * The destination path relative to the app's resources/output directory.
   */
  to?: string
  
  /**
   * The glob patterns to filter files.
   */
  filter?: Array<string> | string
}

Application Directory Structure

Packaged App Structure

MyApp.app/
├── Contents/
│   ├── MacOS/
│   │   └── MyApp              # Executable
│   ├── Resources/
│   │   ├── app.asar           # Your application
│   │   ├── app.asar.unpacked/ # Unpacked files
│   │   └── ...                # Extra resources
│   ├── Frameworks/            # Electron framework
│   └── Info.plist

Optimizing Application Size

1. Remove Unnecessary Dependencies

Move development dependencies to devDependencies:
package.json
{
  "dependencies": {
    "electron-store": "^8.0.0"
  },
  "devDependencies": {
    "electron": "^28.0.0",
    "electron-builder": "^24.0.0",
    "webpack": "^5.0.0"
  }
}

2. Exclude Development Files

{
  "build": {
    "files": [
      "**/*",
      "!src${/*}",
      "!**/*.ts",
      "!**/*.map",
      "!**/{.eslintrc,.prettierrc,tsconfig.json}",
      "!**/node_modules/**/{test,__tests__,tests}${/*}"
    ]
  }
}

3. Use Compression

{
  "build": {
    "compression": "maximum",
    "asar": true
  }
}
Compression levels: store (no compression), normal (default), maximum

4. Remove Metadata

{
  "build": {
    "removePackageScripts": true,
    "removePackageKeywords": true
  }
}

Accessing Packaged Resources

From Main Process

main.js
import { app } from 'electron'
import path from 'path'
import fs from 'fs'

// App directory (inside asar)
const appPath = app.getAppPath()
const configPath = path.join(appPath, 'config', 'settings.json')

// Resources directory (outside asar)
const resourcesPath = process.resourcesPath
const assetPath = path.join(resourcesPath, 'assets', 'icon.png')

// Read from asar
const config = fs.readFileSync(configPath, 'utf8')

// Read from resources
const icon = fs.readFileSync(assetPath)

From Renderer Process

renderer.js
const path = require('path')
const fs = require('fs')

// Using preload script (recommended)
const { getResourcePath } = require('electron').ipcRenderer

// Or direct access (if nodeIntegration is enabled)
const isDev = process.env.NODE_ENV === 'development'
const basePath = isDev
  ? process.cwd()
  : process.resourcesPath

const assetPath = path.join(basePath, 'assets', 'data.json')

Build Hooks for File Processing

Use hooks to process files during the build:
electron-builder.config.js
export default {
  // ... other config
  hooks: {
    onNodeModuleFile: async (file) => {
      // Return true to force include, false to exclude
      if (file.endsWith('.d.ts')) {
        return false // Exclude TypeScript definition files
      }
    }
  }
}
See the Build Configuration page for more information on build hooks.

Development vs Production

Development Configuration

{
  "build": {
    "asar": false,
    "compression": "store",
    "directories": {
      "output": "dist-dev"
    }
  }
}

Production Configuration

{
  "build": {
    "asar": true,
    "compression": "maximum",
    "directories": {
      "output": "dist"
    },
    "electronFuses": {
      "enableEmbeddedAsarIntegrityValidation": true,
      "onlyLoadAppFromAsar": true
    }
  }
}

Build docs developers (and LLMs) love