How can I bundle a precompiled binary with electron

The problem is that electron-builder or electron-packager will bundle your dependency into the asar file. It seems that if the dependency has a binary into node_modules/.bin it is smart enough to not package it.

This is the documentation for asar packaging for electron-builder on that topic. It says

Node modules, that must be unpacked, will be detected automatically

I understand that it is related to existing binaries in node_modules/.bin.

If the module you are using is not automatically unpacked you can disable asar archiving completely or explicitly tell electron-builder to not pack certain files. You do so in your package.json file like this:

  "build": {
    "asarUnpack": [
      "**/app/node_modules/some-module/*"
    ],

For your particular case

I ran into the same issue with ffmpeg and this is what I’ve done:

  • Use ffmpeg-static. This package bundles statically compiled ffmpeg binaries for Windows, Mac and Linux. It also provides a way to get the full path of the binary for the OS you are running: require('ffmpeg-static').path
  • This will work fine in development, but we still need to troubleshoot the distribution problem.
  • Tell electron-builder to not pack the ffmpeg-static module:

    “build”: {
    “asarUnpack”: [
    “**/app/node_modules/ffmpeg-static/*”
    ],

  • Now we need to slightly change the code to get the right path to ffmpeg with this code: require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') (if we are in development the replace() won’t replace anything which is fine).

If you are using webpack (or other javascript bundler)

I ran into the issue that require('ffmpeg-static').path was returning a relative path in the renderer process. But the issue seemed to be that webpack changes the way the module is required and that prevents ffmpeg-static to provide a full path. In the Dev Tools the require('ffmpeg-static').path was working fine when run manually, but when doing the same in the bundled code I was always getting a relative path. So this is what I did.

  • In the main process add this before opening the BrowserWindow: global.ffmpegpath = require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked'). The code that runs in the main process is not bundled by webpack so I always get a full path with this code.
  • In the renderer process pick the value this way: require('electron').remote.getGlobal('ffmpegpath')

Leave a Comment