Ir para o conteúdo principal

Atualizando Aplicativos

Existem várias maneiras de fornecer atualizações automáticas para seu aplicativo Electron. A maneira mais fácil, suportada oficialmente é utilizando o framework embutido Squirrel e o módulo autoUpdater do Electron.

Utilizando armazenamento de objeto em nuvem (serverless)

Para um fluxo serverless simples, o módulo autoUpdater do Electron pode verificar se existem atualizações disponívels apontando para uma URL estática que contenha os últimos metadados de versionamento.

Quando uma nova versão está disponível, o metadado precisa ser publicado para o armazenamento em nuvem juntamente da versão em si. O formato dos metadados é diferente para macOS e Windows.

Publicando metadados de versionamento

Com o Electron Forge, você pode lançar atualizações de arquivos estáticos publicando artefatos de metadados diretamente do ZIP Maker (macOS) com o comando macUpdateManifestBaseUrl e do Squirell.Windows Maker (Windows) com remoteReleases.

Veja o artigo do Forge Atualizações automáticas do S3 para um exemplo completo.

Publicações manuais

No macOS, o Squirell.Mac pode receber atualizações lendo o arquivo releases.json com o seguinte formato JSON:

releases.json
{
"currentRelease": "1.2.3",
"releases": [
{
"version": "1.2.1",
"updateTo": {
"version": "1.2.1",
"pub_date": "2023-09-18T12:29:53+01:00",
"notes": "Theses are some release notes innit",
"name": "1.2.1",
"url": "https://mycompany.example.com/myapp/releases/myrelease"
}
},
{
"version": "1.2.3",
"updateTo": {
"version": "1.2.3",
"pub_date": "2024-09-18T12:29:53+01:00",
"notes": "Theses are some more release notes innit",
"name": "1.2.3",
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
}
}
]
}

No Windows, o Squirell.Windows pode receber atualizações lendo o arquivo RELEASES gerado durante o processo de build. Este arquivo detalha o pacote delta .nupkg para o qual atualizar.

RELEASES
B0892F3C7AC91D72A6271FF36905FEF8FE993520 electron-fiddle-0.36.3-full.nupkg 103298365

Estes arquivos devem ficar no mesmo diretório da sua versão, dentro de uma estrutura de pastas que esteja de acordo com a plataforma e arquitetura do seu aplicativo.

Como por exemplo:

my-app-updates/
├─ darwin/
│ ├─ x64/
│ │ ├─ my-app-1.0.0-darwin-x64.zip
│ │ ├─ my-app-1.1.0-darwin-x64.zip
│ │ ├─ RELEASES.json
│ ├─ arm64/
│ │ ├─ my-app-1.0.0-darwin-arm64.zip
│ │ ├─ my-app-1.1.0-darwin-arm64.zip
│ │ ├─ RELEASES.json
├─ win32/
│ ├─ x64/
│ │ ├─ my-app-1.0.0-win32-x64.exe
│ │ ├─ my-app-1.0.0-win32-x64.nupkg
│ │ ├─ my-app-1.1.0-win32-x64.exe
│ │ ├─ my-app-1.1.0-win32-x64.nupkg
│ │ ├─ RELEASES

Lendo os metadados de versionamento

A maneira mais fácil de consumir os metadados é instalando o update-electron-app, um módulo Node.js que configura o autoUpdater e exibe ao usuário uma janela de diálogo nativa.

For static storage updates, point the updateSource.baseUrl parameter to the directory containing your release metadata files.

main.js
const { updateElectronApp, UpdateSourceType } = require('update-electron-app')

updateElectronApp({
updateSource: {
type: UpdateSourceType.StaticStorage,
baseUrl: `https://my-bucket.s3.amazonaws.com/my-app-updates/${process.platform}/${process.arch}`
}
})

Using update.electronjs.org

A equipe do Electron mantém update.electronjs.org, um webservice gratuito e de código aberto que os aplicativos Electron podem usar para se auto-atualizar. O serviço é destinado para apps Electron que atendem os seguintes critérios:

  • O app roda no macOS ou no Windows
  • O app tem um repositório GitHub público
  • Builds são publicadas em GitHub Releases
  • Builds are code-signed (macOS only)

A forma mais fácil de usar este serviço é instalando o update-electron-app, um módulo Node.js pre-configurado para ser usado com update.electronjs.org.

Instale o módulo usando seu gerenciador de pacotes Node.js de preferência:

npm install update-electron-app

Em seguida, importe o pacote do atualizador no arquivo principal do projeto:

main.js
require('update-electron-app')()

Por padrão, este módulo irá verificar atualizações na inicialização do aplicativo, e a cada dez minutos. Quando uma atualização for encontrada, ela será baixada automaticamente em segundo plano. Quando o download é concluído, uma caixa de diálogo será exibida permitindo que o usuário reinicie o aplicativo.

Se precisar personalizar sua configuração, você pode passar argumentos para o update-electron-app ou usar o serviço de atualização diretamente.

Usando outros serviços de atualização

Se você estiver desenvolvendo um aplicativo Electron privado, ou se não é publicado versões no GitHub Releases, pode ser necessário executar o seu próprio servidor de atualização.

Passo 1: Implementando um servidor de atualização

Dependendo de suas necessidades, você pode escolher um destes:

  • Hazel – Servidor de Atualização para aplicativos privados ou de código aberto que podem ser implantados gratuitamente na Vercel. Ele puxa do GitHub Releases e utiliza o poder dos GitHub CDN.
  • Nuts - Também usar GitHub Releases, mas armazena em cache as atualizações do app no disco e suporta repositórios.
  • electron-resease-server - Fornece um painel para a manipulação de versões e não requer lançamentos que se originam do GitHub.
  • Nucleus - Um servidor de atualização completo para Electron apps mantido pela Atlassian. Suporta múltiplas aplicações e canais; usar um armazenamento de arquivo estático para diminuir o custo do servidor.

Dado que você fez implementar no seu servidor de atualizações, você pode modificar o código do seu 'app' para receber e aplicar as atualizações com o módulo [AutoUpdater] do Electron.

Passo 2: Recebendo atualizações no seu 'app'

Primeiro, importe os módulos necessários no arquivo principal do projeto. O código a seguir pode variar para diferentes softwares de servidor, mas ele funciona como descrito ao usar o Hazel.

Verifique seu ambiente de execução!

Por favor, certifique-se de que o código abaixo será executado apenas no seu aplicativo empacotado, e não em desenvolvimento. Você pode usar a API app.isPackaged para verificar o ambiente.

main.js
const { app, autoUpdater, dialog } = require('electron')

Em seguida, construa a URL do feed do servidor de atualização e informe ao autoUpdater sobre ele:

main.js
const server = 'https://your-deployment-url.com'
const url = `${server}/update/${process.platform}/${app.getVersion()}`

autoUpdater.setFeedURL({ url })

Como etapa final, verifique se há atualizações. O exemplo abaixo irá verificar a cada minuto:

main.js
setInterval(() => {
autoUpdater.checkForUpdates()
}, 60000)

Once your application is packaged, it will receive an update for each new GitHub Release that you publish.

Passo 3: Notificando os usuários quando atualizações estiverem disponíveis

Agora que você configurou um Sistema de Atualização básico para sua aplicação, você precisa garantir que o usuário será notificado quando houver uma atualização. Isto pode ser realizado usando os eventos da API do AutoUpdater:

main.js
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Reiniciar', 'Mais Tarde'],
title: 'Atualização Disponivel',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail:
'Uma nova versão foi Baixada. Restart the application to apply the updates.'
}

dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})

Certifique-se também de que os erros estão sendo tratados. Segue um exemplo como debugar e enviar para o stderr:

main.js
autoUpdater.on('error', (message) => {
console.error('Ocorreu um erro ao atualizar o aplicativo')
console.error(message)
})
Manipulando atualizações manualmente

Como as solicitações feitas pelo autoUpdate não estão sob seu controle direto, você pode encontrar situações difíceis ao manusear (como caso o servidor de atualização estiver por trás de uma autenticação). O campo url suporta o protocolo file://, o que significa que, com algum esforço, você pode evitar o aspecto de comunicação do servidor do processo, enviando sua atualização a partir de um diretório local. Aqui está um exemplo de como isso pode funcionar.

Update server specification

For advanced deployment needs, you can also roll out your own Squirrel-compatible update server. For example, you may want to have percentage-based rollouts, distribute your app through separate release channels, or put your update server behind an authentication check.

Squirrel.Windows and Squirrel.Mac clients require different response formats, but you can use a single server for both platforms by sending requests to different endpoints depending on the value of process.platform.

main.js
const { app, autoUpdater } = require('electron')

const server = 'https://your-deployment-url.com'
// e.g. for Windows and app version 1.2.3
// https://your-deployment-url.com/update/win32/1.2.3
const url = `${server}/update/${process.platform}/${app.getVersion()}`

autoUpdater.setFeedURL({ url })

Windows

A Squirrel.Windows client expects the update server to return the RELEASES artifact of the latest available build at the /RELEASES subpath of your endpoint.

For example, if your feed URL is https://your-deployment-url.com/update/win32/1.2.3, then the https://your-deployment-url.com/update/win32/1.2.3/RELEASES endpoint should return the contents of the RELEASES artifact of the version you want to serve.

https://your-deployment-url.com/update/win32/1.2.3/RELEASES
B0892F3C7AC91D72A6271FF36905FEF8FE993520 https://your-static.storage/your-app-1.2.3-full.nupkg 103298365

Squirrel.Windows does the comparison check to see if the current app should update to the version returned in RELEASES, so you should return a response even when no update is available.

macOS

When an update is available, the Squirrel.Mac client expects a JSON response at the feed URL's endpoint. This object has a mandatory url property that maps to a ZIP archive of the app update. All other properties in the object are optional.

https://your-deployment-url.com/update/darwin/0.31.0
{
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
"name": "1.2.3",
"notes": "Theses are some release notes innit",
"pub_date": "2024-09-18T12:29:53+01:00"
}

If no update is available, the server should return a 204 No Content HTTP response.