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
-
Router
Tentei usar oreact-router-dom
comBrowserRouter
e vi a minha primeira build prod sem navegação. Até que encontrei esse outro tabnews e entendi que não rolava usarBrowserRouter
no electron - felizmente, só precisei substituir porHashRouter
e funcionou perfeitamente sem ter que refatorar nada. -
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. -
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! :)