Opbygning af en elektronapplikation med create-react-app
Ingen webpack-konfiguration eller "skubbe ud" nødvendig.
Jeg har for nylig bygget en Electron-app ved hjælp af create-react-app . Jeg havde heller ikke brug for at skide med Webpack eller "skubbe" min app ud. Jeg vil lede dig igennem, hvordan jeg opnåede dette.
Jeg blev tiltrukket af ideen om at bruge create-react-app, fordi den skjuler webpakkens konfigurationsoplysninger. Men min søgning efter eksisterende guider til brug af Electron og create-react-app sammen bar ikke nogen frugt, så jeg dykkede bare ind og fandt ud af det selv.
Hvis du føler dig utålmodig, kan du dykke lige ind og se på min kode. Her er GitHub-repoen til min app.
Inden vi går i gang, lad mig fortælle dig om Electron and React, og hvorfor create-react-app er et så godt værktøj.
Elektron og reagerer
React er Facebooks JavaScript-ramme.
Et JavaScript-bibliotek til opbygning af brugergrænseflader - Reager
Et JavaScript-bibliotek til opbygning af brugergrænsefladerfacebook.github.io
Og Electron er GitHubs ramme til opbygning af desktop-platform-apps i JavaScript.
Elektron
Byg desktop-apps på tværs af platforme med JavaScript, HTML og CSS. electron.atom.io
De fleste bruger webpack til den konfiguration, der er nødvendig for React-udvikling. webpack er et konfigurations- og buildværktøj, som det meste af React-samfundet har vedtaget over alternativer som Gulp og Grunt.
Konfigurationsomkostningerne varierer (mere om dette senere), og der er mange kogeplader og applikationsgeneratorer tilgængelige, men i juli 2016 frigav Facebook Incubator et værktøj,Opret-reager-app . Det skjuler det meste af konfigurationen og lader udvikleren bruge enkle kommandoer, såsom npm start
og npm run build
til at køre og opbygge deres apps.
Hvad skubbes ud, og hvorfor vil du undgå det?
create-react-app giver visse antagelser om en typisk React-opsætning. Hvis disse antagelser ikke er noget for dig, er der mulighed for at skubbe en applikation ud ( npm run eject
). Skubning af en applikation kopierer hele den indkapslede konfiguration af create-react-app til dit projekt og leverer en kedelpladekonfiguration, som du kan ændre, som du ønsker.
Men dette er en envejs tur. Du kan ikke fortryde udstødning og gå tilbage. Der har været 49 udgivelser (fra dette indlæg) af create-react-app, der hver især forbedrer. Men for et udkastet program skal du enten afstå fra disse forbedringer eller finde ud af, hvordan du anvender dem.
En udskudt konfiguration er over 550 linjer, der spænder over 7 filer (fra dette indlæg). Jeg forstår ikke det hele (ja, det meste faktisk) og det vil jeg ikke.
Mål
Mine mål er enkle:
- undgå at skubbe React-appen ud
- minimer lim for at få React og Electron til at arbejde sammen
- bevare standarder, antagelser og konventioner foretaget af Electron og create-react-app / React. (Dette kan gøre det lettere at bruge andre værktøjer, der antager / kræver sådanne konventioner.)
Grundlæggende opskrift
- kør for
create-react-app
at generere en grundlæggende React-applikation - løb
npm install --save-dev electron
- tilføj
main.js
fraelectron-quick-start
(vi omdøber det tilelectron-starter.js
, for at gøre det klart) - rediger opkald til
mainWindow.loadURL
(inelectron-starter.js
) for at brugelocalhost:3000
(webpack-dev-server) - tilføj en hovedpost til
package.json
forelectron-starter.js
- tilføj et køremål for at starte Electron til
package.json
npm start
efterfulgt afnpm run electron
Trin 1 og 2 er ret ligetil. Her er koden til trin 3 og 4:
const electron = require('electron'); // Module to control application life. const app = electron.app; // Module to create native browser window. const BrowserWindow = electron.BrowserWindow; const path = require('path'); const url = require('url'); // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow; function createWindow() { // Create the browser window. mainWindow = new BrowserWindow({width: 800, height: 600}); // and load the index.html of the app. mainWindow.loadURL('//localhost:3000'); // Open the DevTools. mainWindow.webContents.openDevTools(); // Emitted when the window is closed. mainWindow.on('closed', function () { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. mainWindow = null }) } // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow); // Quit when all windows are closed. app.on('window-all-closed', function () { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit() } }); app.on('activate', function () { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (mainWindow === null) { createWindow() } }); // In this file you can include the rest of your app's specific main process // code. You can also put them in separate files and require them here.
(Gist)
Og i trin 5 og 6:
{ "name": "electron-with-create-react-app", "version": "0.1.0", "private": true, "devDependencies": { "electron": "^1.4.14", "react-scripts": "0.8.5" }, "dependencies": { "react": "^15.4.2", "react-dom": "^15.4.2" }, "main": "src/electron-starter.js", "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "electron": "electron ." } }
(Gist)
Når du kører npm-kommandoerne i trin 7, skal du se dette:

Du kan foretage liveændringer i React-koden, og du bør se dem afspejles i den kørende Electron-app.

Dette fungerer okay for udvikling, men har to mangler:
- produktion vil ikke bruge
webpack-dev-server
. Det skal bruge den statiske fil fra opbygningen af React-projektet - (lille) gener for at køre begge npm-kommandoer
Angivelse af loadURL i produktion og udvikling
Under udvikling kan en miljøvariabel specificere url for mainWindow.loadURL
(in electron-starter.js
). Hvis env var findes, bruger vi det; ellers bruger vi den statiske produktions HTML-fil.
Vi tilføjer et npm-kørselsmål (til package.json
) som følger:
"electron-dev": "ELECTRON_START_URL=//localhost:3000 electron ."
Opdatering: Windows-brugere skal gøre følgende: (takket være @bfarmilo)
”electron-dev”: "set ELECTRON_START_URL=//localhost:3000 && electron .”
I electron-starter.js
ændrer vi mainWindow.loadURL
opkaldet som følger:
const startUrl = process.env.ELECTRON_START_URL || url.format({ pathname: path.join(__dirname, '/../build/index.html'), protocol: 'file:', slashes: true }); mainWindow.loadURL(startUrl);
(Gist)
Der er et problem med dette: create-react-app
(som standard) bygger en, index.html
der bruger absolutte stier. Dette mislykkes, når det indlæses i Electron. Heldigvis er der en konfigurationsmulighed for at ændre dette: Indstil en homepage
ejendom i package.json
. (Facebook-dokumentation om ejendommen er her.)
Så vi kan indstille denne egenskab til den aktuelle mappe og npm run build
vil bruge den som en relativ sti.
"homepage": "./",
Brug af formand til at styre reaktions- og elektronprocesser
For nemheds skyld foretrækker jeg ikke at gøre det
- starte / administrere både React dev server og Electron processer (jeg vil hellere beskæftige mig med en)
- vent på, at React dev-serveren starter, og start derefter Electron
Formænd er et godt processtyringsværktøj. Vi kan tilføje det,
npm install --save-dev foreman
og tilføj følgende Procfile
react: npm startelectron: npm run electron
(Gist)
Det handler om (1). For (2) kan vi tilføje et simpelt nodeskript ( electron-wait-react.js
), der venter på, at React dev-serveren starter, og derefter starter Electron.
const net = require('net'); const port = process.env.PORT ? (process.env.PORT - 100) : 3000; process.env.ELECTRON_START_URL = `//localhost:${port}`; const client = new net.Socket(); let startedElectron = false; const tryConnection = () => client.connect({port: port}, () => { client.end(); if(!startedElectron) { console.log('starting electron'); startedElectron = true; const exec = require('child_process').exec; exec('npm run electron'); } } ); tryConnection(); client.on('error', (error) => { setTimeout(tryConnection, 1000); });
(Gist)
BEMÆRK: Foreman udligner portnummeret med 100 for forskellige typer processer. (Se her.) Såelectron-wait-react.js
trækker 100 for at indstille portnummeret på React dev-serveren korrekt.
Nu skal du ændre Procfile
react: npm startelectron: node src/electron-wait-react
(Gist)
Endelig ændrer vi køremålene for package.json
at erstatte electron-dev
med:
"dev" : "nf start"
Og nu kan vi udføre:
npm run dev
UPDATE (1/25/17): Jeg har tilføjet følgende afsnit som svar på nogle brugerkommentarer (her og her). De har brug for adgang til Electron indefra reageringsappen, og et simpelt krav eller import kaster en fejl. Jeg bemærker en løsning nedenfor.
Adgang til Electron fra React-appen
En Electron-app har to hovedprocesser: Electron-værten / -indpakningen og din app. I nogle tilfælde vil du gerne have adgang til Electron indefra din applikation. For eksempel vil du muligvis få adgang til det lokale filsystem eller bruge Electron's ipcRenderer
. Men hvis du gør følgende, får du en fejl
const electron = require('electron') //or import electron from 'electron';
Der er nogle diskussioner om denne fejl i forskellige problemer med GitHub og Stack Overflow, som denne. De fleste løsninger foreslår ændringer af webpack-konfiguration, men dette kræver, at applikationen skubbes ud.
Der er dog en simpel løsning / hack.
const electron = window.require('electron');
const electron = window.require('electron'); const fs = electron.remote.require('fs'); const ipcRenderer = electron.ipcRenderer;
Afslutter
For nemheds skyld er her en GitHub repo, der har alle ændringerne ovenfor med tags til hvert trin. Men der er det ikke meget arbejde at starte en Electron-applikation, der bruger create-react-app. (Dette indlæg er meget længere end koden og de ændringer, du har brug for for at integrere de to.)
Og hvis du bruger create-react-app, kan du tjekke mit indlæg, fejlfindingstest i WebStorm og create-react-app.
Tak for læsningen. Du kan tjekke flere af mine indlæg på justideas.io
OPDATERING (2/2/17). En læser, Carl Vitullo, foreslog at bruge inpm start
stedet for
npm run dev
og indsendte en pull-anmodning med ændringerne på GitHub. Disse tweaks er tilgængelige i denne gren.