electron-builder
electron-builder is the release toolchain that turns an Electron application into installable macOS, Windows, and Linux artifacts. It packages app files into an ASAR by default, rebuilds native dependencies for Electron, creates formats such as DMG, NSIS, AppImage, deb, and rpm, signs supported targets, produces update metadata, and can publish releases. It is a build-time CLI and Node API, not code that belongs in the renderer bundle or replaces Electron itself.
electron-builder is the practical default when an Electron team wants installers, signing, update metadata, and publishing under one configuration. Do not install it for simple bundling, and do not mistake its cross-platform target list for freedom from native runners, certificates, or release engineering.
Use it if
- You need one configuration to produce signed installers and archives for macOS, Windows, and Linux
- You want NSIS, DMG, AppImage, deb, rpm, or store targets without assembling separate packaging tools yourself
- Your release flow needs electron-updater metadata and artifact publishing to GitHub, S3, Spaces, Keygen, or a generic server
- You have native Node dependencies and want a standard install-app-deps step that rebuilds them against the Electron ABI
- You only need an unpacked Electron application bundle: @electron/packager has a narrower job and substantially less signing, publishing, and update configuration
- You expect one Linux runner to produce every production artifact: the multi-platform guide says native dependencies generally need the target platform, and macOS code signing only works on macOS
- Your team will not budget for signing credentials and platform accounts: macOS distribution needs Apple-issued certificates and notarization, while unsigned Windows installers trigger publisher warnings
- You use Yarn Plug'n'Play and cannot switch this workspace to node_modules: the v26 README explicitly requires Yarn 3 projects to set nodeLinker to node-modules
- You want a small, predictable first build with no downloaded toolchain: electron-builder downloads required helper tools on demand, while target-specific work can also require Wine, Mono, rpm, bsdtar, or Snapcraft
Setup reality
Install electron-builder as a development dependency, then add the app metadata Electron distribution expects: name, description, version, author, a stable appId, platform icons, and a build configuration in package.json or a separate JS, TS, YAML, JSON, or JSON5 file. The first run is not lightweight. electron-builder downloads Electron and target helper binaries on demand, fills persistent caches, packages files into app.asar by default, and may reveal that a required entry file was excluded by your files patterns. Yarn 3 Plug'n'Play is not supported; set nodeLinker: node-modules. Native production dependencies must match Electron's ABI, so the README recommends a postinstall script using electron-builder install-app-deps. Add nodeGypRebuild for native addons owned by the app itself, and unpack binaries that cannot run from ASAR. Cross-platform does not mean build-anywhere: native dependencies normally compile on their target OS, macOS signing requires macOS, and Linux-to-Windows builds rely on Wine or the provided builder image. Shipping adds credentials and cost. macOS direct distribution needs an Apple Developer certificate, hardened runtime, and notarization; Windows should use an OV, EV, or Azure signing path. Credential discovery can otherwise yield an unsigned artifact, so production CI should set forceCodeSigning. Publishing requires provider tokens and an explicit --publish policy is safer because v26's implicit CI publishing behavior is deprecated for v27. Auto-update is a separate electron-updater app dependency, works only with supported installer targets, and should be tested from an installed signed build rather than only in development.
Patterns
Add a minimal package.json build configurationconfigure-minimal-app
{
"name": "acme-notes",
"version": "1.0.0",
"description": "Desktop notes app",
"author": "Acme Inc.",
"main": "dist/main.js",
"scripts": {
"dist": "electron-builder"
},
"build": {
"appId": "com.acme.notes",
"productName": "Acme Notes"
}
}Keep appId stable after release; operating systems and update flows use application identity, not only the display name.
Package an unpacked app for quick testingbuild-unpacked-directory
npx electron-builder --dirThis skips creation of DMG, NSIS, deb, and other distributables. It is faster for smoke tests but does not test the installer or auto-update path.
Choose explicit platform targetsbuild-platform-targets
npx electron-builder --mac dmg zip
npx electron-builder --win nsis portable
npx electron-builder --linux AppImage debRun production builds on suitable target runners. macOS signing only works on macOS, and native dependencies usually cannot be cross-compiled safely.
Include only runtime fileslimit-packaged-files
appId: com.acme.notes
files:
- dist/**/*
- package.json
- node_modules/**/*
- '!**/*.map'
- '!**/__tests__/**'Once custom files patterns are present, inspect the unpacked app and confirm the main entry, preload scripts, migrations, and runtime assets survived.
Ship files outside app.asarcopy-runtime-resources
extraResources:
- from: assets/models
to: models
filter:
- '**/*'
# In Electron main-process code:
# const modelDir = path.join(process.resourcesPath, 'models')extraResources paths start at the project root and land in the application's resources directory; access them through process.resourcesPath at runtime.
Keep a native binary outside ASARunpack-native-binaries
asar: true
asarUnpack:
- node_modules/better-sqlite3/**/*
- bin/**/*Electron redirects matching paths to app.asar.unpacked, but child processes and native loaders still need testing from the packaged app. Smart unpack handles many native modules automatically.
Match native modules to Electron after installrebuild-native-dependencies
{
"scripts": {
"postinstall": "electron-builder install-app-deps",
"dist": "electron-builder"
}
}This rebuilds production dependencies for Electron's ABI. For native addons stored in your own app rather than a dependency, configure nodeGypRebuild too.
Use a predictable artifact namename-release-artifacts
artifactName: '${productName}-${version}-${os}-${arch}.${ext}'
directories:
output: release/${version}Keep ${ext} in the template and include ${arch} when publishing more than one architecture, or separate builds can overwrite each other.
Fail CI instead of shipping unsignedrequire-code-signing
forceCodeSigning: true
mac:
hardenedRuntime: true
notarize: true
win:
target: nsis
# Inject CSC_LINK and CSC_KEY_PASSWORD from CI secrets.Without forceCodeSigning, electron-builder can continue when it finds no signing identity. Never store certificate data or passwords in the configuration file.
Publish artifacts to GitHub Releasespublish-github-release
publish:
provider: github
owner: acme
repo: notes-desktop
# CI command, with GH_TOKEN in the environment:
npx electron-builder --publish onTagState the publish policy explicitly. v26's implicit behavior based on tokens, CI, and script names is deprecated and scheduled to be disabled in v27.
Check for packaged-app updatesenable-auto-updates
import { app } from 'electron';
import { autoUpdater } from 'electron-updater';
app.whenReady().then(() => {
autoUpdater.checkForUpdatesAndNotify();
});Install electron-updater as an application dependency and configure publish metadata. Do not call setFeedURL; test this from an installed, signed build using a supported target.
Run a targeted build from Nodebuild-programmatically
const { build, Platform, Arch } = require('electron-builder');
const artifacts = await build({
targets: Platform.LINUX.createTarget(['AppImage'], Arch.x64),
config: {
appId: 'com.acme.notes',
directories: { output: 'release' },
},
});
console.log(artifacts);Version 26 supports this CommonJS API and returns artifact paths. Programmatic builds still download tools and obey the same host-platform restrictions as the CLI.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| @electron-forge/cli | npm | You want an official Electron build workflow with project scaffolding, makers, publishers, and plugins in one system |
| @electron/packager | npm | You only need platform application bundles and will handle installers, signing, and publishing separately |
| electron-winstaller | npm | You specifically need a Windows installer and prefer a focused tool over a cross-platform release suite |
| create-dmg | npm | You already have a packaged macOS app and only need to turn it into a polished DMG |