Neste tutorial, veremos como criar um aplicativo de desktop usando o framework Electron. Este ambiente de programação permite-lhe desenvolver GUIs utilizando as linguagens Web JavaScript, HTML e CSS que são compatíveis com vários sistemas operativos.
Configurar o ambiente de programação
Para este tutorial, vamos utilizar o editor de código VS Code.
A estrutura Electron funciona com o software Node.js. Descarregue e instale a versão mais recente
ou introduza os seguintes comandos no Linux
sudo apt-get install nodejs npm
Verifique as versões instaladas. Isto ajudá-lo-á a verificar a compatibilidade das bibliotecas.
node -v npm -v
No terminal VSCode, crie o seu diretório de trabalho
mkdir ElectronApp && cd ElectronApp
No diretório da aplicação, introduza o comando de inicialização para criar os ficheiros predefinidos
npm init
Introduza as informações solicitadas. Note que o Electron usa o ficheiro principal.js como ponto de entrada.
Press ^C at any time to quit. package name: (electronapp) version: (1.0.0) description: custom electron app for dev and tutorials entry point: (index.js) principal.js test command: git repository: keywords: author: aranacorp license: (ISC) MIT About to write to D:\Formation\Javascript\Electron\ElectronApp\package.json: { "name": "electronapp", "version": "1.0.0", "description": "custom electron app for dev and tutorials", "main": "principal.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "electron ." }, "author": "aranacorp", "license": "MIT" }
Pode então instalar o eletrão
npm install --save-dev electron
Quando o ficheiro package.json tiver sido criado, adicione a seguinte linha aos scripts
"start": "electron ."
Este scirpt é utilizado para lançar a aplicação com o comando
npm start
Criação da primeira aplicação Electron
Neste exemplo, vamos recuperar as versões do node e do electron como no tutorial básico. Também vamos adicionar um campo de entrada para definir um possível URL.
Para criar a aplicação, vamos criar 5 ficheiros
- principal.js gere o ciclo de vida da aplicação
- index.html contém a página HTML
- ./src/ac_style.css contém o estilo da página HTML
- preload.js contém o script de pré-carregamento, incluindo funções de comunicação entre processos
- renderizador.js contém as funções que gerem a página HTML
- main.js
const { app, BrowserWindow, ipcMain } = require('electron') const path = require('node:path') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600, //icon:'./src/logo_araignee.png', webPreferences: { preload: path.join(__dirname, 'preload.js') } }) ipcMain.on('set-url', (event, url) => { console.log("url set to: ",url) }) //win.webContents.openDevTools() //Open devtools on launch win.setTitle(app.getName()+"@"+app.getVersion()); win.loadFile('index.html') } app.whenReady().then(() => { createWindow() app.on('activate', () => { //for macOS if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() })
- index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"> <link rel="stylesheet" href="./src/ac_style.css"> </head> <body> <h1>Hello World!</h1> <p>Nous utilisons les versions: </p> <ul> <li>Node.js : <span id="node-version"></span></li> <li>Chromium : <span id="chrome-version"></span></li> <li>Electron : <span id="electron-version"></span></li> </ul> <p>CurrentURL: <span id="current-url">None</span></p> <p>URL: <input id="url"/> <button id="btn" type="button">Set</button></p> <script src="./renderer.js"></script> </body> </html>
- ./src/ac_style.css
:root { --bg-color: #161616; --btn-color: #346751; --title-color: #3aaa35; /*#c84b31; #ff9900*/ --text-color: #ecdbba; } body { background-color: var(--bg-color); color: var(--text-color); font-family: Arial, sans-serif; margin: 0; padding: 0; } h1 { color: var(--title-color); } p { font-size: 18px; margin-bottom: 20px; }
- preload.js
const { contextBridge, ipcRenderer } = require('electron') contextBridge.exposeInMainWorld('electronAPI', { setURL: (url) => ipcRenderer.send('set-url', url) }) window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const dependency of ['chrome', 'node', 'electron']) { replaceText(`${dependency}-version`, process.versions[dependency]) } })
- renderer.js
const urlInput = document.getElementById('url') const currURL = document.getElementById('current-url') const setButton = document.getElementById('btn') setButton.addEventListener('click', () => { const url = urlInput.value window.electronAPI.setURL(url) currURL.innerHTML = url })
Resultados
Depois de o script ter sido iniciado com “npm start”, abre-se uma janela. Pode atualizar o URL utilizando o campo de entrada e o botão “Set”.
Criar um executável para a aplicação
Para criar o executável, utilizamos o pacote electron-packager
npm install --save-dev electron-packager
Pode então compilar o seu projeto utilizando o comando
npx electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]
Exemplo para Windows
npx electron-packager . myElectronApp --overwrite --asar --platform=win32 --arch=x64 --icon=./src/logo_araignee.ico --prune=true --out=release-builds
Exemplo para Linux
npx electron-packager . myElectronApp --overwrite --asar --platform=linux --arch=x64 --icon=./src/logo_araignee.ico --prune=true --out=release-builds
OS | platform | architecture |
Windows | win32 | x86, x86_64, and arm64 |
Linux | linux | x86, x86_64, armv7l, arm64, and mips64el |
macOS | darwin | x86_64, arm64, and universal |
No ficheiro package.json, adicione estes dois scripts como atalhos;
"build": "electron-packager . myElectronApp --overwrite", "clean": "rm -rf release-builds"
É possível criar um executável com o comando
npm run build
ou eliminar pastas geradas com
npm run clean
Pode agora lançar a aplicação a partir do ficheiro executável myElectronApp.exe
Bónus: Criar uma aplicação com Electron e React
Vamos criar a mesma aplicação com Electron e React. Para isso, criamos um novo projeto
npm init electron-app@latest react-electron-app -- --template=webpack
cd react-electron-app
npm install --save-dev @babel/core @babel/preset-react babel-loader
Em seguida, modifique o ficheiro webpack.rules.js
{ test: /\.jsx?$/, use: { loader: 'babel-loader', options: { exclude: /node_modules/, presets: ['@babel/preset-react'] } } }
npm install -save react react-dom
- index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello World!</title> </head> <body> <div id="root"></div> </body> </html>
- renderer.js
import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./app.jsx"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <App /> </React.StrictMode> );
- app.jsx
import React from "react"; class App extends React.Component { constructor(props) { super(props); this.state = { url: "None", }; } setUrl = () => { //() => {this.setState({url: document.getElementById("url").value})} this.setState({url: document.getElementById("url").value}) } render() { return ( <div> <h1>Hello World!</h1> <p>Welcome to your Electron application.</p> <p>CurrentURL: <span id="current-url">{this.state.url}</span></p> <p>URL: <input id="url" /> <button id="btn" type="button" onClick={this.setUrl}>Set</button></p> </div> ); } } export default App;
Pode então lançar a aplicação com o comando
npm start
Para criar o executável
npm run make