Electron
Anteriormente conhecido como Atom Shell.
A partir do Electron 28, o suporte a ESM está disponível.
Referência: https://github.com/Elanis/web-to-desktop-framework-comparison
NW.js (anteriormente conhecido como node-webkit) é o principal concorrente do Electron. Ambos são soluções de aplicativos de desktop multiplataforma baseadas na arquitetura Chromium+Node.js.
NW.js foi fundado 2 anos antes do Electron, mas o Electron agora é muito mais popular que o NW.js, e é improvável que essa situação mude no futuro.
NW.js foi fundado 2 anos antes do Electron, mas o Electron agora é muito mais popular que o NW.js, e é improvável que essa situação mude no futuro.
- O Electron separa o processo Principal (Main) do processo do Renderizador (Renderer).
Dentro do processo do Renderizador, existem dois contextos, executando código Node.js e código do lado do navegador, respectivamente.
O modelo do Electron separa as preocupações, mas a relevância desse design de separação forçada de preocupações é altamente questionável.
O design de IPC excepcionalmente complicado e os intermináveis "shows" de segurança tornam a experiência de desenvolvimento extremamente ruim.
O design de IPC excepcionalmente complicado e os intermináveis "shows" de segurança tornam a experiência de desenvolvimento extremamente ruim.
- NW.js é baseado na arquitetura Chrome Apps, onde Node.js e o renderizador Chromium compartilham o mesmo processo, permitindo que os módulos Node.js sejam usados diretamente no lado do navegador.
Como os plugins nativos do Node.js podem ser carregados diretamente no lado do navegador, o desempenho do NW.js é muito superior ao do Electron, que depende de IPC, e das soluções baseadas em WASM.
Existem dois modos: contexto separado e contexto misto:
- No modo de contexto separado, há dois ambientes: o contexto Node e o contexto Web. O contexto Node é o ambiente de execução para módulos Node.js, e o contexto Web é o ambiente de execução para scripts NW.js.
Devido ao isolamento das variáveis globais em diferentes contextos, problemas de igualdade de referência podem ocorrer facilmente. - No modo de contexto misto, apenas um contexto é usado.
Não ocorrem problemas de igualdade de referência, mas existe o risco de o contexto ser contaminado por bibliotecas de terceiros.
- O ponto de entrada do Electron é o script JavaScript do processo Principal.
- O ponto de entrada do NW.js é principalmente um arquivo HTML, mas também pode ser um script JavaScript.
A documentação do Electron é significativamente superior à do NW.js. A documentação do último tem pouca legibilidade e falta gravemente de atualizações.
- O Electron não possui proteção de código-fonte nativa, exigindo o uso de soluções de bytecode V8 como bytenode ou electron-vite.
- O NW.js possui um compilador de código oficial nwjc. O princípio é o mesmo do bytenode, mas a implementação é ligeiramente diferente:
Como o NW.js pode modificar diretamente o V8, ele evita muitas das limitações presentes em soluções externas como o bytenode.
- O Electron tem muitos usuários corporativos, sendo o VSCode o projeto mais famoso.
- Apesar de ter sido lançado mais cedo, o NW.js tem uma base de usuários relativamente pequena.
Jogos criados com RPG Maker são provavelmente a maior fonte atual de usuários do NW.js.
Neutralinojs não empacota o Chromium, mas usa o WebView do sistema operacional.
Como esperado, o WebView pode causar problemas de compatibilidade, portanto, não é considerado uma solução de nível de produção.
Como esperado, o WebView pode causar problemas de compatibilidade, portanto, não é considerado uma solução de nível de produção.
Neutralinojs não suporta sistemas Windows mais antigos: https://github.com/neutralinojs/neutralinojs/issues/486
Tauri usa Rust e o WebView do sistema operacional, não suporta módulos Node.js e exige que a API seja escrita em Rust.
Como esperado, o WebView pode causar problemas de compatibilidade, portanto, não é considerado uma solução de nível de produção.
Como esperado, o WebView pode causar problemas de compatibilidade, portanto, não é considerado uma solução de nível de produção.
Além das plataformas de desktop, Tauri também planeja suportar iOS e Android.
- O isolamento de contexto cria complexidade desnecessária.
- A API carece de uniformidade; existem vários métodos para remover a barra de menu de uma janela.
- Estratégia de iteração de versão principal muito rápida.
- Falta de um framework de teste útil.
O processo principal de um aplicativo Electron, que é o ponto de entrada de todo o aplicativo. Pode haver apenas uma instância.
O processo em um aplicativo Electron responsável pela interface do usuário. É iniciado pelo processo principal e pode haver várias instâncias.
Por padrão, o processo do renderizador não tem a capacidade de acessar diretamente os módulos Node.js nativos.
Todos os módulos Node.js precisam ser chamados indiretamente através de uma interface de isolamento de contexto criada por um script de preload.
Todos os módulos Node.js precisam ser chamados indiretamente através de uma interface de isolamento de contexto criada por um script de preload.
A integração do Node.js no processo do renderizador pode ser ativada usando a opção
nodeIntegration: true ao criar a janela.Por padrão, o script de preload é isolado do ambiente host do processo do renderizador.
Ambos podem se comunicar apenas através de
Ambos podem se comunicar apenas através de
contextBridge e window.postMessage.Esse comportamento pode ser cancelado através de
contextIsolation: false.contextBirdge.exposeInMainWorld é o único método para expor APIs do script de preload ao ambiente host do processo do renderizador.Os tipos de dados disponíveis para a ponte são limitados:
Além dos tipos básicos estruturáveis e clonáveis, também é permitido enviar funções, Promises, objetos de erro, etc., mas ainda não satisfaz as necessidades comuns.
Além dos tipos básicos estruturáveis e clonáveis, também é permitido enviar funções, Promises, objetos de erro, etc., mas ainda não satisfaz as necessidades comuns.
A ponte também possui as seguintes características:
- Para o preload, a exposição da API é única e não pode ser repetida; as alterações da API não podem ser sincronizadas com o ambiente host.
- Para o ambiente host, as funções remotas aparecerão como código nativo (native code).
- Os objetos expostos são congelados, portanto, para o ambiente host, a API não é gravável.
- Para tipos não suportados, podem ocorrer três resultados diferentes:
undefined, cópia de propriedade de objeto ou erro.
O processo do renderizador pode usar ipcRenderer para fazer solicitações ao processo principal.
Este IPC suporta dois modos:
- send: envia mensagens apenas para ipcMain.
- invoke: modo request-reply.
Devido ao isolamento de contexto, chamar
ipcRenderer.send/invoke no processo do renderizador é muito inconveniente.O processo principal pode fazer solicitações ao processo do renderizador, mas apenas se obtiver primeiro o objeto WebContents do processo do renderizador.
O objeto WebContents pode ser obtido de duas maneiras:
- O renderizador primeiro faz uma solicitação ao principal, e o
event.senderrecebido pelo principal é o objeto WebContents. - O principal retém o BrowserWindow ao criar a janela e então usa
BrowserWindow.webContents.
Devido ao isolamento de contexto, registrar ouvintes de eventos no processo do renderizador é muito inconveniente.
Interface padrão MessagePort.
https://www.electronjs.org/docs/latest/tutorial/message-ports
https://www.electronjs.org/docs/latest/tutorial/message-ports
Aplicável à comunicação entre principal e renderizador, e entre renderizadores.
Como principal e renderizador podem se comunicar via ipcMain e ipcRenderer,
este método de comunicação é usado principalmente para a comunicação entre renderizadores.
Como principal e renderizador podem se comunicar via ipcMain e ipcRenderer,
este método de comunicação é usado principalmente para a comunicação entre renderizadores.
Antes de estabelecer a comunicação, é necessário primeiro passar o objeto MessagePort via ipcMain e ipcRenderer.
A IPC pode ser implementada usando protocolos de rede, como HTTP e WebSocket.
Considerando o quão tedioso é estabelecer a comunicação entre o Principal e o Renderizador (contexto Web) no Electron,
usar protocolos de rede como IPC é também um método para reduzir a complexidade.
usar protocolos de rede como IPC é também um método para reduzir a complexidade.
- A interface IPC será exposta a outros programas na mesma rede.
- O desempenho é pior do que outros métodos.
Devido a diferentes ABIs, o Electron não pode usar diretamente os módulos nativos do Node.js. Os módulos devem ser compilados especificamente para o Electron.
https://www.electronjs.org/docs/latest/tutorial/devtools-extension
O Electron suporta limitadamente a API de extensões do Chrome e pode carregar algumas ferramentas de desenvolvimento.
No Windows e macOS, a API embutida do Electron pode ser usada para configurar a inicialização no arranque:
https://www.electronjs.org/docs/latest/api/app#appsetloginitemsettingssettings-macos-windows
https://www.electronjs.org/docs/latest/api/app#appsetloginitemsettingssettings-macos-windows
No entanto, a implementação das funcionalidades relacionadas está cheia de bugs lamentáveis:
- https://github.com/electron/electron/issues/32657
- https://github.com/electron/electron/issues/33308
Esta implementação não suporta argumentos personalizados.
Uma solução especializada para persistir configurações em arquivos JSON.
Por baixo, usa o módulo conf do mesmo autor, suportando JSON Schema e migração de versão baseada em
Por baixo, usa o módulo conf do mesmo autor, suportando JSON Schema e migração de versão baseada em
package.json.Um banco de dados de documentos que roda em memória, com persistência intermitente no sistema de arquivos.
Desenvolvimento não ativo.
Um módulo puramente JavaScript que usa JSON como banco de dados.
Basicamente, é uma classe para ler e escrever JSON, sem nada de notável.
O autor parou de mantê-lo.
Um banco de dados avançado que combina RxJS e PouchDB.
Devido ao uso do ecossistema PouchDB, o Electron é oficialmente suportado.
Devido ao uso do ecossistema PouchDB, o Electron é oficialmente suportado.
Um exemplo típico de número de downloads desproporcional ao número de estrelas no Github; a base de usuários real não é grande.
Embora o autor tenha se esforçado muito neste projeto, ele ainda tem uma curva de aprendizado íngreme para novos usuários.
Embora o autor tenha se esforçado muito neste projeto, ele ainda tem uma curva de aprendizado íngreme para novos usuários.
Este projeto também depende de muitos pacotes que o autor não pode controlar, tornando-o muito frágil:
- RxJS
- PouchDB
- pouchdb-find (o método find de RxCollection usa diretamente este pacote, portanto, compartilha os mesmos defeitos)
- mquery (código copiado)
A partir da versão v10, o RxDB começou a se preparar para se desvincular do PouchDB.
Considerando a popularidade do projeto, a manutenibilidade e a confiabilidade de suas dependências, o RxDB não vale a pena ser usado.
No Node.js, o PouchDB usa o LevelDB como camada de armazenamento através do módulo levelup.
A camada subjacente do módulo levelup é um módulo nativo, mas ele suporta nativamente o Electron, portanto não precisa ser processado com electron-rebuild para ser usado.
A camada subjacente do módulo levelup é um módulo nativo, mas ele suporta nativamente o Electron, portanto não precisa ser processado com electron-rebuild para ser usado.
O PouchDB não foi projetado para cenários multiprocesso, possui muitas otimizações baseadas em memória, e sua camada Node.js LevelDB também não suporta multiprocesso.
Portanto, ao usar com Electron, suas instâncias devem ser criadas apenas no processo Principal e, em seguida, expostas ao Renderizador via IPC para acesso.
Portanto, ao usar com Electron, suas instâncias devem ser criadas apenas no processo Principal e, em seguida, expostas ao Renderizador via IPC para acesso.
pouchdb-find é uma extensão oficial usada para implementar a sintaxe de consulta no estilo Mongo.
Este pacote possui muitos problemas, incluindo, mas não se limitando a:
- Resultados incorretos mesmo com índices:
https://github.com/pouchdb/pouchdb/issues/7810
Embora o problema relacionado tenha sido fechado, ainda encontrei o mesmo problema no pacote v7.2.2. - Descartando seletores:
https://github.com/pouchdb/pouchdb/issues/6572
https://github.com/pouchdb/pouchdb/issues/6371
Depender deste pacote para consultas é claramente não confiável.
Sem suporte a Mongo, o PouchDB não tem valor de uso.
Sem suporte a Mongo, o PouchDB não tem valor de uso.
A versão anterior foi lançada em 2020. Os bugs não foram corrigidos desde então, e muitos problemas críticos de bugs foram ignorados pelos mantenedores.
Suas definições de tipo
Suas definições de tipo
@types/pouchdb também são antigas (adaptadas para PouchDB v6.4).O autor do RxDB também mencionou nas notas de lançamento do RxDB v10 que o PouchDB não está sendo bem mantido.
https://github.com/pouchdb/pouchdb/issues/3224
Como um módulo nativo que não suporta Node-API (N-API),
better-sqlite3 precisa ser processado com electron-rebuild antes de poder ser usado, o que pode levar a problemas de bloqueio de dependência.
better-sqlite3 precisa ser processado com electron-rebuild antes de poder ser usado, o que pode levar a problemas de bloqueio de dependência.
Este é o módulo SQLite3 mantido pela equipe Ghost.
Este módulo foi reescrito com base na Node-API a partir da versão v5.
Este módulo foi reescrito com base na Node-API a partir da versão v5.
A interface de callback também define `this`, o que impede o uso de funções de seta.
Para obter um wrapper de Promise, é necessário instalar o wrapper de terceiros node-sqlite.
Cada instância de Database desta biblioteca é apenas uma conexão, e não há condições de corrida.
Quando uma transação é iniciada, todas as instruções executadas na instância farão parte dessa transação.
Portanto, é sempre necessário criar uma nova instância para iniciar uma transação; para reutilizar instâncias, isso significa a necessidade de criar um pool, o que complica a solução.
Quando uma transação é iniciada, todas as instruções executadas na instância farão parte dessa transação.
Portanto, é sempre necessário criar uma nova instância para iniciar uma transação; para reutilizar instâncias, isso significa a necessidade de criar um pool, o que complica a solução.
Esta é a biblioteca SQLite3 usada pelo VSCode, é um fork de sqlite3.
https://www.electronjs.org/docs/latest/tutorial/application-distribution
Essencialmente, a distribuição de aplicativos é realizada através da distribuição de pacotes binários pré-construídos do Electron que satisfazem uma estrutura de diretórios específica.
Por exemplo, no Windows, o método de distribuição manual é baixar o pacote binário pré-construído do Electron da versão e plataforma correspondentes,
criar um diretório
Posteriormente, geralmente é necessário renomear o executável do Electron e alterar seu ícone.
Por exemplo, no Windows, o método de distribuição manual é baixar o pacote binário pré-construído do Electron da versão e plataforma correspondentes,
criar um diretório
resources/app no diretório do Electron e, em seguida, copiar todos os arquivos do projeto para este diretório.Posteriormente, geralmente é necessário renomear o executável do Electron e alterar seu ícone.
O pacote oficial electron-packager pode ser usado para simplificar as etapas acima.
Um formato de arquivo similar ao tar, específico do Electron, projetado para empacotar projetos Electron em um único arquivo.
O arquivo
O arquivo
resources/app.asar pode substituir a pasta resources/app.Alguns módulos nativos exibirão este erro após serem empacotados como arquivos asar.
Quando não empacotado com asar, o Electron pode encontrar e carregar corretamente os módulos nativos.
Quando não empacotado com asar, o Electron pode encontrar e carregar corretamente os módulos nativos.
Usar
--asar.unpack=*.{node,dll} em vez de --asar do electron-packager pode resolver este problema.Referências:
- https://github.com/electron/packager/issues/424
- https://github.com/electron/asar/issues/75
app.isPackaged é amplamente usado para determinar se um aplicativo Electron está em ambiente de desenvolvimento ou produção.No entanto, seu método de determinação é bastante contraintuitivo; ele verifica se o nome do arquivo executável do Electron ainda é electron.
Este pacote é usado para automatizar a criação de aplicativos para várias plataformas.
- Suporta a configuração de ícones de arquivo executável.
- Suporta a exclusão de devDependencies para reduzir o tamanho do pacote.
electron-packager não possui o recurso de ignorar caminhos de empacotamento por meio de um arquivo de ignore, e embora tenha havido um PR para um arquivo
(as razões da rejeição careciam de lógica e suporte factual).
A falta desse recurso torna o electron-packager um pacote inútil, pois, a menos que muitos parâmetros de ignore sejam adicionados na linha de comando, ele empacotará o ambiente de desenvolvimento junto.
.electronignore, ele foi rejeitado(as razões da rejeição careciam de lógica e suporte factual).
A falta desse recurso torna o electron-packager um pacote inútil, pois, a menos que muitos parâmetros de ignore sejam adicionados na linha de comando, ele empacotará o ambiente de desenvolvimento junto.
Quando a opção
Após examinar o código-fonte, descobriu-se que o programa simplesmente executa todas as tarefas em paralelo, o que, no Electron v28, significa baixar 10 Electrons simultaneamente.
Considerando a largura de banda do servidor e a largura de banda do cliente de download, esse paralelismo descontrolado apenas aumenta a probabilidade de encontrar erros de rede.
--all está ativada, este projeto usa recursos de E/S e CPU significativamente mais do que o necessário para as tarefas que executa.Após examinar o código-fonte, descobriu-se que o programa simplesmente executa todas as tarefas em paralelo, o que, no Electron v28, significa baixar 10 Electrons simultaneamente.
Considerando a largura de banda do servidor e a largura de banda do cliente de download, esse paralelismo descontrolado apenas aumenta a probabilidade de encontrar erros de rede.
Uma solução de código aberto para instaladores do Windows.
Suportado por electron-builder.
Suportado pelo pacote da comunidade electron-wix-msi.
O formato UWP, suportado a partir do Windows 8, pode ser publicado na Microsoft Store.
electron-builder pode usar a ferramenta MakeAppx para empacotar o programa como appx.
O formato principal suportado pela Microsoft a partir de 2018, destinado a substituir o MSI, para sistemas Windows 10 e superiores, pode ser publicado na Microsoft Store.
- A comunidade Electron ainda não possui uma solução de empacotamento MSIX.
- O provedor de soluções de empacotamento Advanced Installer suporta o empacotamento de projetos Electron como MSIX.
- A Ferramenta de Empacotamento MSIX oficial da Microsoft pode ser usada para reempacotar instaladores EXE ou MSI como MSIX:
https://docs.microsoft.com/en-us/windows/msix/packaging-tool/create-app-package
O Electron tinha uma biblioteca de teste oficialmente mantida baseada em ChromeDriver, Spectron, mas acabou sendo descontinuada no início de 2022 devido à falta de mantenedores.
Uma alternativa potencial para Spectron é o Playwright.
No entanto, até o Playwright v1.16, os testes baseados em Playwright ainda são um recurso experimental e, em grande parte, indisponíveis:
No entanto, até o Playwright v1.16, os testes baseados em Playwright ainda são um recurso experimental e, em grande parte, indisponíveis:
- Não é possível depurar erros.
- evaluate não suporta a importação de módulos Node.js.
Uma biblioteca para criar camadas de sobreposição de janela.
Desenvolvimento e empacotamento de programas Electron em uma única solução.
Empacotamento e distribuição de programas Electron em uma única solução.
A documentação é inconsistente a ponto de ser lamentável.
O Electron usa uma ABI diferente da versão do Node.js, portanto, não pode usar diretamente módulos nativos baixados por npm e yarn visando a versão atual do Node.js.
electron-rebuild é a ferramenta para resolver esse problema.
electron-rebuild é a ferramenta para resolver esse problema.
Por razões de manutenibilidade, não é recomendado usar módulos nativos que exijam electron-rebuild.
- electron-rebuild não consegue selecionar a versão correta da ABI, o que pode fazer com que módulos que dependem de electron-rebuild se tornem uma dependência difícil de atualizar.
https://github.com/electron/electron-rebuild/issues/886 - Embora pertença ao repositório oficial, electron-rebuild frequentemente não consegue acompanhar as últimas versões do Electron.