app-builder-lib
app-builder-lib is the engine inside electron-builder. It exposes the programmatic build function, platform and architecture target maps, packager classes, lifecycle hooks, signing types, publishing integration, and the large configuration model used to turn an Electron application into unpacked directories, archives, and native installers. It is build-time Node tooling, not code to ship inside an Electron renderer or main-process bundle, and most application teams should consume it through electron-builder.
Do not install app-builder-lib directly for an ordinary Electron application; use electron-builder and its documented API. Reach for this package only when you are writing build infrastructure that genuinely needs Packager-level control and can track the monorepo's version changes.
Use it if
- You are building custom release automation that needs electron-builder's build engine as a JavaScript API rather than its CLI
- You need to construct platform, target, and architecture maps dynamically from your own orchestration code
- You maintain an Electron build integration that needs Packager events, cancellation, custom platform packagers, or artifact callbacks
- You intentionally want direct access to electron-builder configuration types and packager classes and will pin all related package versions
- You are packaging a normal Electron app: the official programmatic guide imports build and Platform from electron-builder, whose CLI, configuration loading, and dependency alignment are the supported entry point
- You want a small utility dependency: 26.15.3 declares more than thirty direct runtime dependencies plus exact-version peers for DMG and Squirrel.Windows support, before Electron and downloaded build tools are counted
- You expect one machine to produce every native artifact: macOS signing and notarization require Apple tooling and credentials, while Windows and Linux targets have their own host tools, containers, Wine, or target-specific restrictions
- Your build must run offline without preparation: the tool downloads Electron and required helper binaries on demand unless caches and mirrors are provisioned ahead of time
- You need a low-churn public library contract: app-builder-lib is the implementation package of electron-builder, the next 27.x line is native ESM with removed deprecated APIs, and direct consumers absorb those internal migrations sooner
Setup reality
Installing `app-builder-lib` is the smallest step in a large release toolchain. Version 26.15.3 declares Node 14 or later, ships CommonJS and TypeScript declarations, depends on the matching 26.15.3 `builder-util` and `electron-publish`, and declares exact 26.15.3 peers for `dmg-builder` and `electron-builder-squirrel-windows`. npm can install those peers automatically, so direct installs are not lean. Your project still needs Electron, valid package metadata such as name and version, icons, an application entry point, output and build-resource directories, and carefully tested file globs. ASAR is enabled by default; native executables may need `asarUnpack`. Native Node modules are rebuilt for Electron by default and can require Python, a compiler, platform SDKs, or prebuilt binaries for every target architecture. The builder downloads Electron and helper tools on demand, so first runs are slow and CI should persist caches. Cross-platform output is not symmetric: macOS distribution needs signing identities, entitlements, hardened runtime, and Apple notarization credentials; Windows signing needs a certificate or signing service; Linux formats can need tools such as fpm, rpm, snapcraft, Flatpak, or containers. Secrets belong in CI environment variables, not the inline config. Yarn Plug'n'Play is not supported by the parent project without switching to the node-modules linker. Hooks run with filesystem access inside the release process, and a failure can leave partial artifacts. The exported build function resolves to artifact paths, not a deployment result, while publishing introduces provider credentials and release-channel rules. Pin the whole electron-builder package family together, isolate output directories, test an unpacked `dir` target before installers, and prefer importing the same API from `electron-builder` unless you truly need Packager internals.
Patterns
Build default artifacts for the current platformbuild-current-platform
const { build, Platform } = require('app-builder-lib');
const artifacts = await build({
projectDir: process.cwd(),
targets: Platform.current().createTarget(),
config: { appId: 'com.example.notes' },
});
console.log(artifacts);The promise resolves to artifact paths. For a normal app, import this API from electron-builder instead of depending on app-builder-lib directly.
Create an unpacked app for smoke testingbuild-unpacked-directory
const artifacts = await build({
targets: Platform.current().createTarget('dir'),
config: {
directories: { output: 'dist/unpacked-test' },
},
});The dir target skips installer creation and is the fastest way to catch missing files or startup failures before signing and packaging.
Build an x64 NSIS installerbuild-windows-installer
const { build, Platform, Arch } = require('app-builder-lib');
const artifacts = await build({
targets: Platform.WINDOWS.createTarget('nsis', Arch.x64),
config: {
appId: 'com.example.notes',
win: { icon: 'build/icon.ico' },
nsis: { oneClick: false, allowToChangeInstallationDirectory: true },
},
});A distributable Windows build should be signed. Cross-building may require Wine and still does not make every Windows target portable across hosts.
Build multiple Linux package formatsbuild-linux-formats
const artifacts = await build({
targets: Platform.LINUX.createTarget(['AppImage', 'deb'], Arch.x64),
config: {
linux: {
category: 'Utility',
icon: 'build/icons',
},
},
});Each format can require host tools or container support. Building on Linux is the least surprising path for Linux-native packages.
Build a universal macOS DMGbuild-mac-universal
const artifacts = await build({
targets: Platform.MAC.createTarget('dmg', Arch.universal),
config: {
appId: 'com.example.notes',
mac: {
category: 'public.app-category.productivity',
hardenedRuntime: true,
},
},
});Build this on macOS. Distribution also needs a valid signing identity, compatible entitlements, and notarization credentials.
Use an external builder configurationload-config-file
const artifacts = await build({
projectDir: '/workspace/desktop-app',
targets: Platform.current().createTarget(),
config: 'electron-builder.yml',
});The config path is resolved for the selected project. Keep package-family versions pinned so the schema and TypeScript surface agree.
Limit application files and add resourcesselect-packaged-files
await build({
targets: Platform.current().createTarget('dir'),
config: {
files: ['dist/**/*', 'package.json'],
extraResources: [
{ from: 'assets/models', to: 'models', filter: ['**/*'] },
],
},
});Once a positive files pattern is supplied, the default **/* inclusion is not added. Test that the packaged app still contains its entry point and runtime assets.
Keep native binaries outside ASARunpack-native-binaries
await build({
targets: Platform.current().createTarget('dir'),
config: {
asar: true,
asarUnpack: ['**/*.node', '**/vendor/bin/**'],
npmRebuild: true,
nativeRebuilder: 'sequential',
},
});Executable files are often detected automatically, but explicit patterns help unusual layouts. Rebuilding may need platform compilers and Electron-compatible binaries.
Inspect the staged app in a lifecycle hookrun-after-pack-hook
await build({
targets: Platform.current().createTarget('dir'),
config: {
async afterPack(context) {
console.log('staged app:', context.appOutDir);
console.log('platform:', context.electronPlatformName);
},
},
});afterPack runs after the app is packed but before distributable creation and signing. Throwing rejects the build and can leave partial output.
Receive each completed artifactobserve-artifacts
const completed = [];
await build({
targets: Platform.current().createTarget(),
config: {
artifactBuildCompleted(event) {
completed.push({ file: event.file, arch: event.arch });
},
},
});
console.log(completed);This hook reports local artifacts. Uploading or publishing is a separate concern with provider configuration and credentials.
Create an installer from a prepackaged apppackage-prebuilt-app
const artifacts = await build({
prepackaged: '/workspace/prebuilt/MyApp',
targets: Platform.WINDOWS.createTarget('nsis', Arch.x64),
config: { directories: { output: 'dist/installers' } },
});The prepackaged directory must match the target platform and architecture. This separates app packing from installer creation, not cross-platform signing requirements.
Cancel a programmatic buildcancel-build
const {
build, Packager, Platform, CancellationToken,
} = require('app-builder-lib');
const options = { targets: Platform.current().createTarget() };
const token = new CancellationToken();
const packager = new Packager(options, token);
const pending = build(options, packager);
process.once('SIGINT', () => token.cancel());
await pending;Cancellation is cooperative. Downloaded files, staging directories, or partial artifacts may still require normal CI workspace cleanup.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| electron-builder | npm | Most Electron apps that want the supported CLI and programmatic API with aligned internal packages |
| electron-forge | npm | Teams that prefer Electron's integrated scaffolding, packaging, makers, and publishing workflow |
| electron-packager | npm | You only need platform application bundles and will manage installers, signing, and publishing separately |