Executando verificação de segurança...
5

Minha primeira aventura com React, Electron e Vite - de um iniciante para iniciantes

Esse é um post de um n00b para outros n00bs :)

React, Electron, Vite, Typescript e outras loucuras que me meti

Resolvi recentemente fazer um projetinho usando electron - um pouco pra me meter numa confusão que não conhecia ainda e um pouco pra conseguir possibilitar algumas outras pessoas não técnicas a consumirem uma API do Moskit (lugar em que trabalho) sem ter que entender nada de código e nem ter que instalar nada.

Meu foco desde o começo era ter uma GUI e não ficar maluco.

O grande problema é que eu nunca tinha feito nada além de meia dúzia de scripts em JS e algumas análises de dados com pandas.

Me deparei com electron-vite - já ouvi ambos os nomes no fireship.io mas não tinha a menor ideia do que tava me metendo.
Rodei npm create electron-vite e escolhi React como o meu template de projeto.
Ao todo, 4 coisas que eu nunca tinha encostado: React, Typescript, Electron e Vite.

Aqui tá tudo que eu precisei entender pra conseguir buildar meu primeiro appzinho honesto:

Como isso funciona numa visão high-level

O projeto criado tem duas "grandes áreas": O Main e o Renderer. Na minha cabeça fez sentido pensar como back e front, não sei se isso tá certo ou errado, mas a analogia me ajudou a entender melhor sobre a estrutura.

No caso do template que escolhi, tudo que era core do electron roda no main e tudo que é React roda no renderer.

Então no main vai rolar criação de janelas, barra de atalhos da aplicação, tarefas que não rodam na cara do end user, etc.

No renderer, navegação, páginas, interação direta do usuário e tudo mais.

Os dois se comunicam através do ipc que é uma espécie de mensageiro entre as duas áreas - no meu caso, usei pra invocar um worker no main através do envio de um token de api pelo usuário no renderer.

Estrutura importa

O create electron-vite vai gerar essa estrutura de arquivos:

├─┬ dist/electron
│ ├─┬ main
│ │ └── index.ts > Electron-Main
│ └─┬ preload
│ └── index.ts > Preload-Scripts
├─┬ dist
│ └── index.html > Electron-Renderer
├─┬ src
│ └── App.tsx > Componente App do React
├── public > Diretório de recursos usados na hora de buildar

Separation of concerns é uma ótima pra entender essa estrutura. Tudo que for relacionado ao React vai viver dentro de src e relacionado ao electron, dist.

Imagens e qualquer outro tipo de arquivo deve viver dentro de public, ele vai ser servido no root quando for buildar, então se for usar uma imagem no CSS, considere que ela está no root da aplicação, ou seja, só lançar o './img.svg' e ser feliz.

No caso da minha aplicação, como estava usando alguns workers que migrei pra TS, adicionei mais um diretório no /main para os workers e adicionei o caminho no tsconfig.json.

├─┬ dist/electron
│ └─┬ Workers
│ └── Worker.ts

IPC

Como falei antes, o IPC é o mensageiro responsável por levar informação entre o Main e o Renderer de forma bidirecional.

Nos componentes do React é só importar usando import { ipcRenderer } from 'electron' que os métodos tão prontos pra serem usados.

Existem vários métodos vindos do IPC que são tratados de forma diferente no Renderer e no Main - não tem como fugir da documentação aqui. No meu caso, usei para quando ocorra um form submit no React contendo um token de api, meu worker seja chamado no Main e consuma uma API gerando um CSV.

Pra isso usei ipcRenderer.send("mensagem", args) no form submit - a "mensagem" é um canal arbitrário definido por você - essa é a forma do main diferenciar as N possíveis mensagens diferentes que podem chegar usando o mesmo método no Renderer.

Em combinação com isso, no main/index.ts importei o meu Worker.ts e adicionei ipcMain.on("mensagem", (event,args)=>{ Worker(args) }) tratando esse arg no Worker pra ser lido como o token inserido pelo usuário.

Como parti de um template, não precisei configurar nada no preload, mas, se estiver indo no seco, pode ser que tenha que alterar alguma coisa - não cheguei a fazer isso ainda.

Buildando

Pra buildar o dev, é só rodar npm run dev que já vai estar funcionando - HMR é suportado, então pode deixar o dev build aberto enquanto vai trabalhando, qualquer erro já vai aparecer na sua tela instantaneamente.

Quando quiser buildar prod, npm run build vai tentar buildar o instalador - padrão é um .exe, mas você pode adicionar adicionar um target se quiser gerar pra outro OS.

Erros que quebrei a cabeça

  1. Router
    Tentei usar o react-router-dom com BrowserRouter e vi a minha primeira build prod sem navegação. Até que encontrei esse outro tabnews e entendi que não rolava usar BrowserRouter no electron - felizmente, só precisei substituir por HashRouter e funcionou perfeitamente sem ter que refatorar nada.

  2. Imagens não estavam aparecendo
    Essa foi fácil de resolver. Movi todas as imagens pra public e atualizei meu CSS. Pelo o que eu entendi pesquisando, o caminho relativo dá problema depois do bundler, movendo pro public e atualizando o caminho que nem mencionei no tópico de estrutura funciona.

  3. Node Fetch
    Por qualquer motivo meu Worker declarou guerra ao node-fetch e não tava buildando com isso - não consegui identificar por que isso aconteceu, migrei pro Axios e buildou sem problemas. Provavelmente é alguma cagada minha isso aqui.

Pra passar a regua e fechar a conta

Como disse lá no começo, isso aqui é de um n00b para outros n00bs que queiram brincar com React Electron Vite. Não tenho a menor ideia se isso é seguro pra prod ou se cometi alguma gafe nesse texto - no final do dia o que importa pra mim é ter aprendido um monte de coisa nova nessa semaninha que gastei nesse projeto.

Valeu pela leitura e []s! :)

Carregando publicação patrocinada...
3

Tenho uma aplicação em Electron que uso React, TypeScript e Webpack. Não tenho experiência com bundlers, mas acho que trocar o Webpack por Vite seria uma boa, só preciso ter tempo para entender como fazer essa substituição. Criei o projeto a partir do template electron-react-boilerplate.

Sobre o seu problema com o node-fetch, talvez fosse em específico com a versão 3 dele, que é um módulo ESM.

Uma das grandes dificuldades que eu tive no desenvolvimento foi quando precisei fazer chamadas de funções de uma DLL. Tentei usar o node-ffi-napi, mas estava tendo vários problemas e no fim eu mesmo criei uma "ponte" para me comunicar com a DLL. Foi bem demorado até entender como fazer isso tudo dar certo, mas esse artigo me ajudou bastante: A simple guide to load C/C++ code into Node.js JavaScript Applications.

2
1

comecei a mecher com ele, ja quebrei bastante a cabeça para resolver algumas coisa, atualmente estou quebrando a cabeça para adicionar Icone no instalador. se souber como adicionar comenta ai

1

Tenho um projeto usando exatamente o mesmo stack, e resolvi todas as dificuldades relatadas sem grandes problemas, custei a chegar em um boilerplate que me agradasse para desenvolver em cima, mas agora o projeto está redondinho e apto a crescer de forma saudável... A questão de caminho relativo, eu nunca tive problemas, importo minhas imagens da pasta assets sem problema algum.

Pra quem quiser dar uma olhada no projeto, está neste repositório, no branch staging, que é o mais atualizado.