Software comes in many shapes and forms. One of the popular cross-platform, cross-architecture frameworks for building and distributing applications in Electron, which combines the Chromium rendering engine and the Node.js runtime. This makes Electron-based applications relatively easy to create.

If you want to deploy Electron apps in Linux, you can also use snaps as your delivery mechanism. This allows developers to package and ship apps to end users without worrying about the necessary tooling being available on client machines. If an operating system supports snaps, they will run. The only question is, how do Electron apps and snaps work together?

Building snaps with Electron Builder is relatively easy. The framework includes the top-level snap key, with several options that the developers can set. These include snapcraft-supported declarations like confinement, environment variables, build and stage packages, plugs, slots, layouts, compression, and more. By and large, you should be able to build and package snaps with Electron Builder without too many problems.

As outlined in the Snapcraft documentation, the basic process behind Electron Builder targeting snaps is to add a script (named dist in the example), which will then build the application as a snap.

 "scripts": {
    "start": "electron .",
    "dist": "electron-builder --linux snap"
  },

Additional declarations and configurations can be added to the package.json file in the Electron app project directory. However, if you require further charges that are not covered by the snap key, you will need a slightly different approach.

If you feel Electron Builder may be somewhat limited in configurability, you may want to try Electron Packager. In essence, this a command line tool and Node.js library that bundles Electron-based application source code with a renamed Electron executable and supporting files into folders ready for distribution.

Where this gets really interesting is when you use Electron Packager as part of the snap building process. In a way, the approach here is the opposite of what we’ve seen earlier. Instead of using Electron Builder to produce snaps as its artifact, we will embed Electron Packager inside the snaps.

This approach gives more flexibility into what components and overrides get included in the snaps, and you have full control of the snapcraft.yaml as well as all the available, supported keywords.

The basic idea, as outlined in this sample snapcraft.yaml file, is to use the Snapcraft nil plugin, point to the relevant Electron-based app source, and then use electron-packager to build the application in the override-build step:

parts:
  electron-app:
    plugin: nil
    source: some source somewhere
    override-build: |
      npm install electron electron-packager
      npx electron-packager . --overwrite --platform=linux --output=release-build --prune=true
      cp -rv electron-app* $SNAPCRAFT_PART_INSTALL/electron-app
  build-snaps:
    - node/14/stable
  build-packages:
    - unzip
  stage-packages:
    - libnss3
    - libnspr4

For this step to work correctly, you will need a number of build and runtime dependencies, which will differ from project to project. In the example above, we use the node snap, which contains the npm utility, the unzip tool to open the downloaded archives, as well as several runtime dependencies.

The rest of the snapcraft.yaml will include the other necessary declarations, including the app itself, any environment variables it may need, interfaces, and possibly other stage packages.

A third approach, very similar to Electron Packager is to build an app for Linux and place it in a target directory. Then, you can ingest the built artifact into a snap, and provide the additional changes (like interfaces or stage packages) to allow the software to run. This method is outlined in the ubports-installer snapcraft.yaml. However, if you are proficient enough building Electron apps and snaps, the actual implementation is entirely up to you.

Electron apps bring a fair deal of portability and flexibility to the Linux desktop space. With snaps, you can further expand on these capabilities. However, adding abstraction layers can sometimes introduce some complexity. Hopefully, with the use of Electron Builder, Electron Packages and some manual tricks outlined in this article, you can combine the best of both worlds, and create robust, high-quality apps for Linux users.

 If you have any suggestions or new ideas on how to snap Electron apps, we would love to hear from you. Please join the forum and let us know what you think.

Photo by FLY:D on Unsplash.