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 startog npm run buildtil 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

  1. kør for create-react-appat generere en grundlæggende React-applikation
  2. løb npm install --save-dev electron
  3. tilføj main.jsfra electron-quick-start(vi omdøber det til electron-starter.js, for at gøre det klart)
  4. rediger opkald til mainWindow.loadURL(in electron-starter.js) for at bruge localhost:3000(webpack-dev-server)
  5. tilføj en hovedpost til package.jsonforelectron-starter.js
  6. tilføj et køremål for at starte Electron til package.json
  7. npm start efterfulgt af npm 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.loadURLopkaldet 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.htmlder bruger absolutte stier. Dette mislykkes, når det indlæses i Electron. Heldigvis er der en konfigurationsmulighed for at ændre dette: Indstil en homepageejendom i package.json. (Facebook-dokumentation om ejendommen er her.)

Så vi kan indstille denne egenskab til den aktuelle mappe og npm run buildvil 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

  1. starte / administrere både React dev server og Electron processer (jeg vil hellere beskæftige mig med en)
  2. 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.jstræ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.jsonat erstatte electron-devmed:

"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 i npm startstedet for npm run devog indsendte en pull-anmodning med ændringerne på GitHub. Disse tweaks er tilgængelige i denne gren.