使用create-react-app构建电子应用程序

无需Webpack配置或“弹出”。 (No webpack configuration or “ejecting” necessary.)

I recently built an Electron app using create-react-app. I didn’t need to muck about with Webpack, or “eject” my app, either. I’ll walk you through how I accomplished this.

我最近使用create-react-app构建了Electron应用程序 我也不需要为Webpack烦恼,也不需要“弹出”我的应用程序。 我将向您介绍如何完成此操作。

I was drawn to the idea of using create-react-app because it hides the webpack configuration details. But my search for existing guides for using Electron and create-react-app together didn’t bear any fruit, so I just dove in and figured it out myself.

我被使用create-react-app的想法所吸引,因为它隐藏了webpack配置详细信息。 但是,我对现有的将Electron和create-react-app结合使用的指南的搜索并没有取得任何成果,因此我只想自己弄清楚。

If you’re feeling impatient, you can dive right in and look at my code. Here’s the GitHub repo for my app.

如果您不耐烦,可以直接研究一下我的代码。 这是我的应用程序的GitHub存储库

Before we get started, let me tell you about Electron and React, and why create-react-app is such a great tool.

在开始之前,让我告诉您有关Electron和React的知识,以及为什么create-react-app是这么好的工具。

电子与React (Electron and React)

React is Facebook’s JavaScript view framework.

React是FacebookJavaScript视图框架。

A JavaScript library for building user interfaces - ReactA JavaScript library for building user interfacesfacebook.github.io

用于构建用户界面 JavaScript库 -React 用于构建用户界面 JavaScript库 facebook.github.io

And Electron is GitHub’s framework for building cross-platform desktop apps in JavaScript.

Electron是GitHub的框架,用于在JavaScript中构建跨平台的桌面应用程序。

ElectronBuild cross platform desktop apps with JavaScript, HTML, and CSS.electron.atom.io

Electron 使用JavaScript,HTML和CSS构建跨平台的桌面应用程序。 电子原子

Most use webpack for the configuration necessary for React development. webpack is a configuration and build tool that most of the React community has adopted over alternatives like Gulp and Grunt.

大多数使用webpack进行React开发所需的配置。 webpack是配置和构建工具,大多数React社区已经采用了GulpGrunt等替代方案。

The configuration overhead varies (more on this later), and there are many boilerplate and application generators available, but in July 2016 Facebook Incubator released a tool, create-react-app. It hides most of the configuration and lets the developer use simple commands, such as npm start and npm run build to run and build their apps.

配置开销各不相同(稍后会有更多介绍),并且有许多样板和应用程序生成器,但是2016年7月, Facebook Incubator发布了一个工具, create-react-app 它隐藏了大多数配置,并允许开发人员使用简单的命令(例如npm startnpm run build来运行和构建其应用程序。

弹出什么,为什么要避免它? (What is ejecting, and why do you want to avoid it?)

create-react-app makes certain assumptions about a typical React setup. If these assumptions aren’t for you, there is an option to eject an application (npm run eject). Ejecting an application copies all the encapsulated configuration of create-react-app to the your project, providing a boilerplate configuration that you can change as you wish.

create-react-app对典型的React设置进行某些假设。 如果这些假设不适合您,则可以选择退出应用程序( npm run eject )。 弹出应用程序会将所有封装的create-react-app配置复制到您的项目中,从而提供您可以根据需要更改的样板配置。

But this is a one way trip. You can’t undo ejecting and go back. There have been 49 releases (as of this post) of create-react-app, each making improvements. But for an ejected application, you would have to either forgo these improvements or figure out how to apply them.

但这是单程旅行。 您无法撤消弹出并返回。 共有49个版本的create-react-app(截至本文),每个版本都有改进。 但是对于弹出的应用程序,您将不得不放弃这些改进或弄清楚如何应用它们。

An ejected configuration is over 550 lines spanning 7 files (as of this post). I don’t understand it all (well, most of it, actually) and I don’t want to.

弹出的配置超过550行,跨越7个文件(截止本文)。 我不了解所有内容(实际上,大部分内容),我也不想。

目标 (Goals)

My goals are simple:

我的目标很简单:

  • avoid ejecting the React app

    避免弹出React应用
  • minimize glue to get React and Electron working together

    减少胶水,使React和Electron协同工作
  • preserve the defaults, assumptions and conventions made by Electron and create-react-app/React. (This can make it easier to use other tools that assume/require such conventions.)

    保留Electron和create-react-app / React所做的默认设置,假设和约定。 (这可以使使用假定/需要此类约定的其他工具更加容易。)
基本食谱 (Basic Recipe)
  1. run create-react-app to generate a basic React application

    运行create-react-app生成一个基本的React应用程序

  2. run npm install --save-dev electron

    运行npm install --save-dev electron

  3. add main.js from electron-quick-start (we’ll rename it to electron-starter.js, for clarity)

    electron-quick-start添加main.js (为清楚起见,我们将其重命名为electron-starter.js )

  4. modify call to mainWindow.loadURL (in electron-starter.js) to use localhost:3000 (webpack-dev-server)

    修改对mainWindow.loadURL调用(在electron-starter.js )以使用localhost:3000 (webpack-dev-server)

  5. add a main entry to package.json for electron-starter.js

    package.jsonelectron-starter.js添加一个主要条目

  6. add a run target to start Electron to package.json

    添加运行目标以将Electron启动到package.json

  7. npm start followed by npm run electron

    npm start接着npm run electron

Steps 1 and 2 are pretty straightforward. Here’s the code for steps 3 and 4:

步骤1和2非常简单。 这是第3步和第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('http://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)

( 要点 )

And for steps 5 and 6:

对于步骤5和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)

( 要点 )

When you run the npm commands in step 7, you should see this:

在步骤7中运行npm命令时,应该看到以下内容:

You can make live changes to the React code and you should see them reflected in the running Electron app.

您可以实时更改React代码,并且应该在运行的Electron应用程序中看到它们。

This works okay for development, but has two shortcomings:

这样可以很好地进行开发,但是有两个缺点:

  • production won’t use webpack-dev-server. It needs to use the static file from building the React project

    生产将不使用webpack-dev-server 。 它需要使用构建React项目中的静态文件

  • (small) nuisance to run both npm commands

    (小)讨厌同时运行两个npm命令
在生产和开发中指定loadURL (Specifying the loadURL in Production and Dev)

In development, an environment variable can specify the url for mainWindow.loadURL (in electron-starter.js). If the env var exists, we’ll use it; else we’ll use the production static HTML file.

在开发中,环境变量可以指定mainWindow.loadURL的url(在electron-starter.js )。 如果env var存在,我们将使用它。 否则,我们将使用生产静态HTML文件。

We’ll add a npm run target (to package.json) as follows:

我们将添加一个npm运行目标(到package.json ),如下所示:

"electron-dev": "ELECTRON_START_URL=http://localhost:3000 electron ."

Update: Windows users will need to do the following: (thanks to @bfarmilo)

更新:Windows用户将需要执行以下操作:(感谢@bfarmilo )

”electron-dev”: "set ELECTRON_START_URL=http://localhost:3000 && electron .”

In electron-starter.js, we’ll modify the mainWindow.loadURL call as follows:

electron-starter.js ,我们将修改mainWindow.loadURL调用,如下所示:

const startUrl = process.env.ELECTRON_START_URL || url.format({
            pathname: path.join(__dirname, '/../build/index.html'),
            protocol: 'file:',
            slashes: true
        });
    mainWindow.loadURL(startUrl);

(Gist)

( 要点 )

There is a problem with this: create-react-app (by default) builds an index.html that uses absolute paths. This will fail when loading it in Electron. Thankfully, there is a config option to change this: set a homepage property in package.json. (Facebook documentation on the property is here.)

这样做有一个问题: create-react-app (默认情况下)会生成使用绝对路径的index.html 。 将其加载到Electron中时将失败。 幸运的是,有一个配置选项可以更改此设置:在package.json设置一个homepage属性。 (有关此属性的Facebook文档在这里 。)

So we can set this property to the current directory and npm run build will use it as a relative path.

因此,我们可以将此属性设置为当前目录, npm run build会将其用作相对路径。

"homepage": "./",
使用工头来管理React和电子过程 (Using Foreman to Manage React and Electron Processes)

For convenience, I prefer to not

为了方便起见,我宁愿不

  1. launch/manage both React dev server and Electron processes (I’d rather deal with one)

    启动/管理React开发服务器和Electron进程(我宁愿处理一个)
  2. wait for the React dev server to start and then launch Electron

    等待React开发服务器启动,然后启动Electron

Foremen is a good process management tool. We can add it,

工头是一个很好的流程管理工具。 我们可以添加它

npm install --save-dev foreman

and add the following Procfile

并添加以下Procfile

react: npm startelectron: npm run electron

(Gist)

( 要点 )

That deals with (1). For (2), we can add a simple node script (electron-wait-react.js) that waits for the React dev server to start, then starts Electron.

涉及(1)。 对于(2),我们可以添加一个简单的节点脚本( electron-wait-react.js ),该脚本等待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 exec = require('child_process').exec;
            exec('npm run electron');
        }
    }
);

tryConnection();

client.on('error', (error) => {
    setTimeout(tryConnection, 1000);
});

(Gist)

( 要点 )

NOTE: Foreman will offset the port number by 100 for processes of different types. (See here.) So, electron-wait-react.js subtracts 100 to set the port number of the React dev server correctly.

注意:对于不同类型的进程,Foreman会将端口号偏移100。 (请参阅此处 。)因此, electron-wait-react.js减去100即可正确设置React开发服务器的端口号。

Now modify the Procfile

现在修改Procfile

react: npm startelectron: node src/electron-wait-react

(Gist)

( 要点 )

Finally, we’ll change the run targets in package.json to replace electron-dev with:

最后,我们将更改package.json的运行目标,以将electron-dev替换为:

"dev" : "nf start"

And now, we can execute:

现在,我们可以执行:

npm run dev

UPDATE (1/25/17) : I‘ve added the following section in response to some user comments (here and here). They need access to Electron from within the react app and a simple require or import throws an error. I note one solution below.

UPDATE(1/25/17):为了响应一些用户评论( 此处此处 ),我添加了以下部分。 他们需要从react应用程序中访问Electron,简单的require或import会引发错误。 我在下面注意到一种解决方案。

从React App访问电子 (Accessing Electron from the React App)

An Electron app has two main processes: the Electron host/wrapper and your app. In some cases, you’d like access to Electron from within your application. For example, you might want to access the local file system or use Electron’s ipcRenderer. But if you do the following, you’ll get an error

Electron应用程序有两个主要过程:Electron主机/包装程序和您的应用程序。 在某些情况下,您希望从应用程序中访问Electron。 例如,您可能要访问本地文件系统或使用Electron的ipcRenderer 。 但是,如果您执行以下操作,则会收到错误消息

const electron = require('electron')
//or
import electron from 'electron';

There is some discussion about this error in various GitHub and Stack Overflow issues, such as this one. Most solutions propose webpack config changes, but this would require ejecting the application.

有关于这个错误在不同的GitHub和堆栈溢出的问题,像这样的一些讨论一个 。 大多数解决方案建议更改webpack的配置,但这需要弹出应用程序。

However, there is a simple workaround/hack.

但是,有一个简单的解决方法/破解。

const electron = window.require('electron');
const electron = window.require('electron');
const fs = electron.remote.require('fs');
const ipcRenderer  = electron.ipcRenderer;
结语 (Wrapping Up)

For convenience, here is a GitHub repo that has all the changes above, with tags for each step. But, there it isn’t much work to bootstrap an Electron application that uses create-react-app. (This post is much longer than the code and changes you would need to integrate the two.)

为了方便起见,这是一个GitHub存储库 ,其中包含上述所有更改,每个步骤都带有标签。 但是,引导使用create-react-app的Electron应用程序没有太多工作。 (这篇文章比整合两者所需的代码和更改长得多。)

And if you are using create-react-app, you might want to check out my post, Debugging tests in WebStorm and create-react-app.

而且,如果您使用的是create-react-app,则可能需要查看我的文章WebDebugm和create-react-app中的调试测试

Thanks for reading. You can check out more of my posts at justideas.io

谢谢阅读。 您可以在justideas.io上查看我的更多帖子。

UPDATE (2/2/17). A reader, Carl Vitullo, suggested to use npm start instead of npm run dev and submitted a pull request with the changes, on GitHub. These tweaks are available in this branch.

更新(2/2/17)。 读者Carl Vitullo建议在GitHub上使用npm start代替npm run dev并提交包含更改的拉取请求。 这些调整在此分支中可用。

翻译自: https://www.freecodecamp.org/news/building-an-electron-application-with-create-react-app-97945861647c/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值