Three ways to package your Electron apps as snaps

by Igor Ljubuncic on 25 February 2022

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?

Electron Builder

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.

Electron Packager

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.

Build, package yourself

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.

Summary

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.

Newsletter Signup

Related posts

How Snapcraft helps developers map out their application dependencies and efficiently build snaps

One of the core concepts of snaps is cross-distro compatibility. Developers can build their snaps once, and they should run well on more than 40 different Linux distros. But how does one take care of all the required runtime dependencies? By providing them inside the snap, as part of the bundle. In the snap ecosystem, […]

The Future of Snapcraft

System hysteresis, when applied to software, can roughly be defined as an overall lag between desired implementation of code and actual implementation of said code. Ideally, this delay should be minimal, and programmers would be able to make instantaneous changes and improvements to their applications. In reality, things are more complex […]

Craft Parts – Reusable code, Snapcraft style

Throughout the ages, humans have always used simpler tools and materials to create more complex ones. Wood and stone for smelting bronze and iron; iron to create steel; vacuum tubes to create logical gates; logical gates to create advanced arithmetic engines, and so on. Modern software is no different. With Snapcraft in particular, the sn […]