Как создать приложение Electron с ReactJS
Если вы новичок в Electron и предпочитаете использовать ReactJS, возможно, вы наткнулись на этот шаблон на GitHub.
Этот шаблон отличный. Тем не менее, он содержит слишком много модных вещей, которые многим не нужны. Сегодня мы посмотрим как просто оставить свой проект React в Electron и посмотреть, как он работает.
Объединить Electron с Create React App или нет?
Если вы решите объединить Electron с CRA, ваш проект будет выглядеть как обычное приложение React, а whereelectron-starter.js является точкой входа для Electron.
├── Procfile
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.css
├── App.js
├── App.test.js
├── electron-starter.js
├── electron-wait-react.js
├── index.css
├── index.js
└── logo.svg
Если это то, что вы ищете, вот подробное руководство о том, как это сделать.
Но если вы переносите приложение NodeJS в Electron и хотите разделить серверную часть (которая теперь является основным кодом процесса), вы можете попробовать эту структуру.
├── Procfile
├── app
│ ├── config
│ ├── events
│ ├── libs
│ ├── models
│ └── views
│ ├── js
│ │ └── preload.js
│ └── react
│ ├── README.md
│ ├── build
│ ├── package.json
│ ├── public
│ └── src
├── assets
│ └── icon.png
├── electron-wait-react.js
├── main.js
└── package.json
В этом случае main.js будет точкой входа, и папка сборки Electron не будет конфликтовать с папкой сборки CRA.
Настройка Dev и Prod Environment
Поскольку вы не хотите перезапускать свое приложение Electron каждый раз, когда вносите изменения, вы можете указать, чтобы Electron использовал URL-адрес сервера React webpack-dev-server.
const { app, BrowserWindow } = require('electron');
const path = require('path');
const url = require('url');
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1024,
height: 728
});
const startUrl = process.env.ELECTRON_START_URL || url.format({
pathname: path.join(__dirname, 'app/views/react/build/index.html'),
protocol: 'file:',
slashes: true
});
mainWindow.loadURL(startUrl);
Если в качестве переменной среды есть ELECTRON_START_URL, он будет использовать этот URL вместо встроенной версии React.
Благодаря упомянутому выше руководствувы также можете использовать Foreman для управления и регистрации как Electron, так и React.
Вот где Procfile пригодится. В свой Procfile добавьте скрипт npm, который запускает приложение React и приложение Electron:
react: npm run react-start
electron: npm run electron-start
И большая часть магии происходит в package.json.
{
"main": "main.js",
"scripts": {
"start": "nf start -p 3000",
"electron-start": "node electron-wait-react",
"react-start": "cd ./app/views/react && react-scripts start"
},
"devDependencies": {
"electron": "^6.0.9",
"electron-builder": "^21.2.0",
"foreman": "^3.0.1"
},
"directories": {
"buildResources": "assets",
"output": "release"
}
}
Когда вы запускаете npm start, он выполняет обе команды в Procfile на порту 3000.
И вы можете задаться вопросом, что делает electron-wait-react.js?
Как и здесь, мы сделали небольшую настройку для регистрации сообщений из приложения Electron.
Оно ожидает запуска Webpack-dev-сервера React перед запуском приложения Electron.
const net = require('net');
const port = process.env.PORT ? (process.env.PORT - 100) : 3000;
process.env.ELECTRON_START_URL = `http://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 { spawn } = require('child_process');
const ls = spawn('npm run electron', [], { shell: true });
ls.stdout.on('data', (data) => {
console.log(`${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`err: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
}});
tryConnection();
client.on('error', (error) => {
setTimeout(tryConnection, 1000);
});
Установить домашнюю страницу в React package.json
Если вы создаете приложение и видите пустую страницу, это потому, что React не может найти его файлы js и CSS. В вашем package.json приложения React обязательно добавьте:
"homepage": "./"
Используйте nodeIntegration
Наконец, у вас есть React, работающий в Electron, но что, если вы хотите использовать электронные модули внутри React?
После создания окна вы можете добавить nodeIntegration в webPreferences.
mainWindow = new BrowserWindow({
width: 1024,
height: 728,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'app/views/js/preload.js')
}
});
И в вашем приложении React вы можете потребовать его как здесь:
const { ipcRenderer } = window.require("electron");
Другая потенциальная проблема
Приложение React запрещает доступ к файлам вне src. Большинство решений, найденных в Интернете, включают удаление приложения React и отключение этого правила в веб-пакете.
Но в нашем случае использования нам нужны были только изображения для отображения в React, поэтому мы сохранили изображение в формате base64, чтобы обойти эту проблему.
Заключение
Спасибо тем, кто создал учебники и посты об Electron. Ваш вклад сделал изучение Electron менее пугающим.