初探 Electron - 实践篇1
经历过前两篇的洗礼,相信大家已经掌握了 Electron 基本的用法,那么还在等什么,快上手项目试试吧!
查看原文,获得更好的体验哦~
实践篇将以项目主导,我打算由浅入深从零到一去完成该项目,我们来做一个图片文字识别工具 Electron-OCR
,目标如下:
- 图片上传:拖拽或点击上传
- 图片预览:上传完成,直接进入预览页,同时执行文字识别
- 菜单页:简单的导航列表,持续扩充
- 在线演示功能:提供了更多的图片,便于演示效果
- 繁体字识别:繁体字需要调用付费接口,所以需要单独处理,增加了繁体校准功能
- 大图裁切:为了精准识别,需要将图片化繁为简
- 体验优化:图片识别成功后返回结果,并拷贝入粘贴板,支持语音播报
- …
涉及到的技术如下:
electron, electron-compile, electron-reload, react, react-router@4, react-motion, ES6/ES7, Promise, Surperagent, Less, CSS-Modules, eslint, babelrc, cropper, Material-UI…
一、先睹为快
本文的示例代码已经放在了 Github
上,效果图如下:
你可以直接 clone
项目 npm i & npm run start
运行,或者按照本文的思路一步步实现。
二、创建项目
首先,我们本地创建项目 Electron-OCR-demo
,如下:1
2
3# 找到合适的目录,创建项目
cd demos
mkdir Electron-OCR-demo
三、初始化项目
1.创建 app
文件夹,用于存放前端项目主体文件;1
mkdir app
2.创建 service
文件夹,存放请求服务文件以及后端文件;
3.创建 .gitignore
文件:1
vi .gitignore
并写入规则:1
2
3.vscode
node_modules
.log
5.增加 README.md 文件;1
touch README.md
6.初始化 package.json
文件:1
npm init
ok,大功告成,我们来同步一下此时的项目结构:1
2
3
4
5
6.
├── README.md
├── app
├── .gitignore
├── package.json
└── service
四、快速开始
上面我们做了一些前期的准备工作,既然是用 ELectron
来做,那么当然需要安装依赖了:1
npm install electron --save-dev
安装比较慢,建议使用淘宝镜像 cnpm install electron --save-dev
来安装。
我们先来运行一个简单示例,进入 app
目录,添加三个文件,分别是:
1.main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33const { app, BrowserWindow } = require('electron')
const path = require('path')
const url = require('url')
let mainWindow
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600})
// 启动文件入口,如 index.html
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
// 开启 Chromium DevTools
mainWindow.webContents.openDevTools()
// 监听窗口关闭事件
mainWindow.on('closed', function () {
mainWindow = null
})
}
// 加载就绪
app.on('ready', createWindow)
// 监听所有窗口关闭的事件
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
// 激活窗口
app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})
2.index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<script>
// 当然,我们也可以引入其他 js 文件
require('./renderer.js')
</script>
</body>
</html>
3.render.js
1
2
3
4
5
6let myNotification = new Notification('Jartto', {
body: 'Hello Everybody!'
})
myNotification.onclick = () => {
console.log('Click!')
}
如果你不懂这是在干什么,建议先阅读 初探 Electron - 理论篇
最后一步,设置启动项,打开 package.json
:
将 "main": "index.js"
修改为:1
"main": "app/main.js",
同时增加 "start": "electron ."
配置项,指定使用 Electron
启动:1
2
3
4"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
接下来,我们打开命令行,执行:1
npm run start
如果你看到了窗口中的 Hello World!
,那么恭喜你,示例已经正确运行了。
五、继续升级
我们通过手动创建完成了和官网起手项目类似的功能,但路还有些远,我们来做一些升级工作,使用 react
来开发项目。
react
需要额外的一些解析,所以我们借助 electron-compile
来动态编译。
先来安装 react, react-dom, electron-compile
,如果太慢请考虑使用 cnpm
:1
2npm install electron-compilers --save-dev
npm install react react-dom electron-compile --save
因为要预编译文件,所以我们需要为 electron-compile
指定入口文件,在项目根目录下新建 index.js
文件,写入:
注意,记得将 package.json
中,做同步修改 "main": "index.js"
!
1 | const path = require('path'); |
这里先指定在 app
目录下的启动文件 main.js
,其实也就是该目录下的主进程文件。
接下来,我们用 react
改写一下 render.js
,修改如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import React from 'react';
import ReactDOM from 'react-dom';
class MainWindow extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
Good, React Ready!
</div>
);
}
}
const mainWndComponent = ReactDOM.render(
<MainWindow/>, document.getElementById('content'));
最后一步,去 index.html
注册 react
组件:1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<meta charset="UTF-8">
<title> Electron-OCR </title>
</head>
<body>
<div id="content"></div>
<script>
require('./render.js');
</script>
</body>
</html>
基本工作完成,我们试着启动一下:1
npm run start
什么,没启动起来?
Uncaught SyntaxError: Unexpected token import
不要紧张,我们还需要增加个编译规则文件,这很重要!
六、配置编译规则
大家可能都配置过或者间接使用过 babelrc
做转换编译,electron-compile
中的 .compilerc
如出一辙,我们先创建文件:1
touch .compilerc
然后写入我们的规则,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19{
"env": {
"development": {
"application/javascript": {
"presets": ["env", "react"],
"sourceMaps": "inline",
},
"text/less": {
"dumpLineNumbers": "comments"
}
},
"production": {
"application/javascript": {
"presets": ["env", "react"],
"sourceMaps": "none",
}
}
}
}
这里记得安装依赖包文件 babel-preset-env
和 babel-preset-react
1 | npm install babel-preset-env babel-preset-react --save-dev |
OK,搞定,来看看此时我们的 package.json
文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27{
"name": "electron-ocr-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"electron",
"demo"
],
"author": "jartto",
"license": "ISC",
"devDependencies": {
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"electron": "^1.7.10",
"electron-compilers": "^5.9.0"
},
"dependencies": {
"electron-compile": "^6.4.2",
"react": "^16.2.0",
"react-dom": "^16.2.0"
}
}
此时的项目结构应该如下:1
2
3
4
5
6
7
8
9
10
11
12
13.
├── app
│ ├── index.html
│ ├── main.js
│ └── render.js
├── node_modules
│ ├── ...
├── service
├── .compilerc
├── .gitignore
├── index.js
├── package.json
└── README.md
一切就绪,启动 npm run start
,如果你看到:Good, React Ready!
,那么恭喜你,react
和 compile
文件已经可以正常工作了。
六、热启动
太棒了,美中不足的就是 react
不能热加载,没关系,我们还有 electron-reload
,先安装依赖包:1
npm install electron-reload --save-dev
同时,需要在主进程文件 main.js 中增加如下代码:1
2
3
4
5
6
7
8const isDevelopment = true;
if (isDevelopment) {
/* eslint-disable */
require('electron-reload')(__dirname, {
electron: require('${__dirname}/../../node_modules/electron'),
ignored: /node_modules|[\/\\]\./
});
}
重新启动,快更新文件试试吧,热更新也已经就绪了!
七、回顾小结
实践篇,我们从零到一搭建了一个用 react
来开发 electron
的简单框架,完成了支持 es6
的编译配置,同时也添加了热加载。到这里,项目已经初具规模,你可以去做任何想做的事情了~
下一节,我们将继续深入,对框架做一些易用性的优化以及补充,逐步完善项目。传送门在此:初探 Electron - 实践篇2。