Electron🔗
Due to the nature of Electron, building Electron applications as Flatpaks requires a few extra steps compared with other applications. Thankfully, several tools and resources are available which make this much easier.
Este guia fornece informações sobre como a compilação de aplicativos Electron difere de outros aplicativos. Ele também inclui informações sobre as ferramentas para a compilação de aplicativos Electron e como usá-lo.
The guide walks through the manifest file of the sample Electron Flatpak application. Before you start, it is a good idea to take a look at this, either online or by downloading the application.
Compilando o aplicativo de amostra🔗
Embora não seja estritamente necessário, convém tentar compilar e executar o aplicativo de amostra.
To get setup for the build, download or clone the sample app from GitHub, and navigate to the project directory in the terminal. Then to build:
$ flatpak-builder build org.flathub.electron-sample-app.yml --install-deps-from=flathub --force-clean --user --install
Finalmente, o aplicativo pode ser executado com:
$ flatpak run org.flathub.electron-sample-app
Configuração básica🔗
A primeira parte do manifesto do aplicativo de amostra especifica o ID do aplicativo. Ele também configura o runtime e o SDK:
id: org.flathub.electron-sample-app
runtime: org.freedesktop.Platform
runtime-version: '24.08'
sdk: org.freedesktop.Sdk
O runtime do Freedesktop é geralmente o melhor runtime para uso com aplicativos Electron, já que ele é o mais mínimo de todos e outras dependências serão específicas do próprio Electron.
The Electron BaseApp🔗
Next, the manifest specifies that the Electron BaseApp should be used, by
specifying the base and base-version properties in the application
manifest:
base: org.electronjs.Electron2.BaseApp
base-version: '24.08'
BaseApps are described in Dependências. Using the Electron base app is much faster and more convenient than manually building Electron dependencies. It also has the advantage of reducing the amount of duplication on users’ machines, since it means that Electron is only saved once on disk.
A extensão de SDK Node.js🔗
Para criar aplicativos baseados em Electron, você precisa do Node.js disponível no momento da compilação. O Flathub fornece versões LTS do Node.js como extensões para o SDK, para que você possa instalar uma delas e adicioná-la no manifesto de seus aplicativos:
sdk-extensions:
- org.freedesktop.Sdk.Extension.node18
Habilite a extensão adicionando-a a PATH:
build-options:
append-path: /usr/lib/sdk/node18/bin
Observe que o nome da extensão (última parte da notação de DNS reverso, node18 neste exemplo) deve ser o mesmo em sdk-extensions e append-path.
Command🔗
A propriedade command indica que um script chamado run.sh deve ser executado para executar o aplicativo. Isso será explicado em mais detalhes posteriormente.
command: run.sh
Permissões de sandbox🔗
The standard sandbox Diretrizes de permissões also apply to Electron applications. However, Electron’s Wayland support is still experimental. So for display access, only X11 should be used as the default configuration. This will make Electron use Xwayland in a Wayland session and nothing else is required.
The sample app also configures PulseAudio for sound and enables network access:
finish-args:
- --share=ipc
- --device=dri
- --socket=x11
- --socket=pulseaudio
- --share=network
- --env=ELECTRON_TRASH=gio
To allow experimental native Wayland support in Electron>=20, the
--ozone-platform-hint=auto flag can be passed to the program. auto
will choose Wayland when the current session is running under Wayland and
Xwayland or X11 otherwise.
It’s recommended to leave actually enabling Wayland up to the user for now,
i.e. set --socket=x11 in the manifest. Wayland can then be tested with:
flatpak run --socket=wayland org.flathub.electron-sample-app
Enable native Wayland support by default🔗
Nota
Native Wayland support in Electron is still experimental and often unstable. It is advised to stick with the X11/Xwayland configuration above as the default.
To make native Wayland the default for users, --socket=fallback-x11
and --socket=wayland must be used in the manifest.
For Electron versions between 17 and 27, client-side window decorations under
native Wayland can be enabled by passing
--enable-features=WaylandWindowDecorations to the program. For newer
versions of Electron , this isn’t necessary anymore.
Electron uses libnotify on Linux to provide desktop notifications.
Since version 0.8.0 libnotify
automatically uses the notification portal
when inside a sandboxed environment and --talk-name=org.freedesktop.Notifications
is not required anymore. org.electronjs.Electron2.BaseApp includes
libnotify>=0.8.0 since branch/23.08.
To ensure proper mouse cursor scaling on HiDPI displays under Wayland, the
XCURSOR_PATH environment variable must be set to the host’s corresponding
directories:
finish-args:
- --env=XCURSOR_PATH=/run/host/user-share/icons:/run/host/share/icons
Using correct desktop file name🔗
It’s important for Linux applications to set the correct desktop file name. If not, it can lead to problems like missing the window icon under Wayland.
By default Electron uses {appname}.desktop as desktop file name. In Flatpak the name of the desktop file must be the id of the Flatpak.
To tell Electron to use another name you need to set the desktopName key in your package.json e.g. "desktopName": "com.example.MyApp.desktop".
In case you repack a binary, you can use the patch-electron-desktop-filename tool included in the BaseApp.
Each Electron binary ships with resources/app.asar file.
You need to call patch-desktop-filename with this file as argument.
If your application is installed under ${FLATPAK_DEST}/my-app you need to run patch-desktop-filename ${FLATPAK_DEST}/my-app/resources/app.asar.
Opções de compilação🔗
Essas opções de compilação não são estritamente necessárias, mas podem ser úteis se algo der errado. env permite definir uma matriz de variáveis de ambiente; nesse caso, definimos NPM_CONFIG_LOGLEVEL para info, para que npm nos forneça mensagens de erro mais detalhadas.
build-options:
cflags: -O2 -g
cxxflags: -O2 -g
env:
NPM_CONFIG_LOGLEVEL: info
O módulo do aplicativo🔗
A seção final do manifesto define como o módulo do aplicativo deve ser compilado. É aqui que algumas das lógicas adicionais para Electron e Node.js podem ser encontradas.
Por padrão, o flatpak-builder não permite que ferramentas de compilação acessem a rede. Isso significa que as ferramentas que dependem do download de fontes não funcionarão. Portanto, os pacotes Node.js devem ser baixados antes da execução da compilação. Definir a variável de ambiente electron_config_cache significa que elas serão encontradas quando se trata da compilação.
A próxima parte do manifesto descreve como o aplicativo deve ser criado. A opção buildsystem definida com simple é usada, o que permite que uma sequência de comandos seja especificada, que são usados para a compilação. O local do download e o hash do aplicativo também são especificados.
name: electron-sample-app
buildsystem: simple
build-options:
env:
XDG_CACHE_HOME: /run/build/electron-sample-app/flatpak-node/cache
npm_config_cache: /run/build/electron-sample-app/flatpak-node/npm-cache
npm_config_nodedir: /usr/lib/sdk/node18
npm_config_offline: 'true'
subdir: main
sources:
- type: archive
url: https://github.com/flathub/electron-sample-app/archive/1.0.1.tar.gz
sha256: a2feb3f1cf002a2e4e8900f718cc5c54db4ad174e48bfcfbddcd588c7b716d5b
dest: main
Empacotando pacotes NPM🔗
A próxima linha é como os módulos NPM são empacotados como parte de Flatpaks:
- generated-sources.json
Como até mesmo aplicativos simples do Node.js dependem de dezenas de pacotes, seria impraticável especificar todos eles como parte de um arquivo de manifesto. Um script em Python foi, portanto, desenvolvido para baixar pacotes Node.js com o NPM ou Yarn e inclui-los nas fontes do aplicativo.
O script Python requer um arquivo package-lock.json (ou yarn.lock). Este arquivo contém informações sobre os pacotes dos quais um aplicativo depende e pode ser gerado executando npm install --package-lock-only no diretório raiz de um aplicativo. O script é então executado da seguinte maneira:
$ flatpak-node-generator npm package-lock.json
Isso gera o manifesto JSON necessário para compilar os pacotes NPM/Yarn para o aplicativo, que são gerados em um arquivo chamado generated-sources.json. O conteúdo desse arquivo pode ser copiado para o manifesto do aplicativo, mas, como geralmente é muito longo, é melhor vinculá-lo a partir do manifesto principal, o que é feito adicionando generated-source.json como um linha na seção do manifesto, como visto acima.
Iniciando o aplicativo🔗
The Electron app is run through a simple shell script that wraps
zypak. This script can be given any name
but must be specified in the manifest’s command property. See below for a
sample wrapper to launch the app:
- type: script
dest-filename: run.sh
commands:
- zypak-wrapper /app/main/electron-sample-app "$@"
Comandos de compilação🔗
Last but not least, since the simple buildsystem is being used, a list of
build commands must be provided. As can be seen, npm is run with the
npm_config_offline=true environment variable, installing dependencies from
packages that have already been cached. These are copied to /app/main/.
Finally the run.sh script is installed to /app/bin/ so that it will be
on $PATH:
build-commands:
# Install npm dependencies
- npm install --offline
# Build the app; in this example the `dist` script
# in package.json runs electron-builder
- |
. ../flatpak-node/electron-builder-arch-args.sh
npm run dist -- $ELECTRON_BUILDER_ARCH_ARGS --linux --dir
# Bundle app and dependencies
- cp -a dist/linux*unpacked /app/main
# Install app wrapper
- install -Dm755 -t /app/bin/ ../run.sh
Note que se o aplicativo que você está tentando empacotar contiver um bloco build no package.json com instruções para Linux, isso pode fazer com que o electron-builder tente buscar binários adicionais em tempo de compilação (Mesmo se a opção –dir for usada). O exemplo a seguir mostra uma configuração que tentará baixar os binários do AppImage:
"build": {
"linux": {
"target": "AppImage",
}
}
A maneira preferida de corrigir isso não é um patch, mas uma edição em tempo de construção usando jq. O comando a seguir substituirá "target": "AppImage" por "target": "dir":
jq '.build.linux.target="dir"' <<<$(<package.json) > package.json
Make setProgressBar and setBadgeCount work🔗
The setProgressBar and setBadgeCount functions allow showing a progress bar and a badge count in the window icon. It is implemented under Linux using the UnityLauncherAPI. This API is not implemented on every desktop environment. A known desktop environment which implements this is KDE. It is also implemented by the popular Dash to Dock GNOME extension and Plank.
To make it work in Flatpak, the app needs to use the correct desktop filename in its embedded package.json file. The Flatpak also needs the --talk-name=com.canonical.Unity permission. Electron versions earlier than v32 checks checks if it’s running on Unity or KDE before using the UnityLauncherAPI.