第一步:
要做一个electron项目,理论上我们应该从electron-quick-start开始,就是说我们需要如下3个文件:
- package.json,node工程最基本的要求,类似于Java的pom.xml
- main.js 创建窗口,工作在electron的主进程
- index.html 页面,工作在electron的渲染进程
但由于我们要使用antd, antd基于react,它是一个react工程,所以我们从最简单的react工程
create-react-app开始,为什么不用antd的脚手架?官方说这个脚手架只是做demo用,我用antd-init试了一下,发现package.json里东西太多了,而且生成的代码有点莫名其妙,比如index.html里引入了common.js,项目里根本就没有common.js啊,这个脚手架的文档说的也太简单,所以我就不用它了。
在桌面上单击鼠标右键(要同时按住shift键),选择“在此处打开Power Shell窗口(S)”,运行
npx create-react-app dry
注意:
- npx要求npm5.2+,而且安装路径不能有空格,如果你的node已经安装在Program Files下了,先全局安装脚手架
npm install create-react-app -g
, 然后再创建工程create-react-app dry
。 - Win10最好使用Power Shell, 以后都不要再用cmd了,用cmd有些包会安装失败,因为有些脚本执行不了
经过这一步我们立马就有了一个node工程,而且是开箱即用的react工程。
react的脚手架帮我们做了很多工作,并且把webpack的很多配置文件都隐藏了起来,项目看起来非常清爽。如果由于某种原因你必须要修改默认的配置,你可以把默认的配置文件“喷”出来。执行npm run eject
后你就会看到项目里多了很多配置文件。要注意脚手架帮你把配置文件整齐的放在了一个抽屉里,你把它倒出来之后又觉得太乱了,想放回去,这就难办了。
一般情况下我们是不需要eject的,如果你非要eject,请三思。
第二步
现在package.json, index.html都有了,还差一个main.js。
从electron-quick-start拷贝一份main.js,放在src目录下:
将mainWindow.loadFile('index.html')
修改为mainWindow.loadURL('http://localhost:3000')
,注意改为loadURL。
react项目需要编译后才能生成静态文件的,开发时我们需要启动node server。
所以这里要改成URL,内容如下:
const {app, BrowserWindow} = require('electron')
let mainWindow
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadURL('http://localhost:3000')
// Open the 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()
}
})
还需要
- 在
package.json
里加一句"main": "src/main.js",
, main.js是electron的启动脚本,在这里创建了一个窗口并加载页面。 - 在scripts里加一句
"electron": "electron ."
哦,我们还没安装electron呢,现在来安装它:
npm install electron --save-dev
注意:别用cnpm安装,不然打包的时候会卡在那里不动,切记。
好了,我们先来测试一下,在dry下启动两个Power Shell, 先运行npm run start
(或者npm start
),启动好了在另一个shell窗口里运行npm run electron
。
不出意外,你将看到如下画面:
如果你看到的是一片空白。 点击"View >> Toggle Developer Tools",控制台输出
Not allowed to load local resource: file:///C:/Users/XXX/Desktop/dry/index.html。请检查main.js文件,应该是loadURL
,而不是loadFile
。
第三步
开始添加antd,也可以直接看官方文档在 create-react-app 中使用:
①先停掉刚才的服务,连续按3次Ctrl C
。
②npm install antd --save
③为了可以按需加载,我们还需要安装两个东西:npm install react-app-rewired --save
npm install babel-plugin-import --save
④ package.json的scripts里将react-scripts
替换成react-app-rewired
。
⑤在项目根目录里创建config-overrides.js
,内容如下:
const { injectBabelPlugin } = require('react-app-rewired');
module.exports = function override(config, env) {
// do stuff with the webpack config...
config = injectBabelPlugin(
['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }],
config,
);
return config;
};
⑥测试,跟之前一样,分别运行npm run start
和npm run electron
。不出意外你将会看到一个按钮:
试着将"Button",改为"Button666",可以看到electron会自动刷新。按钮显示"Button666"。
到这里就基本告一段落了,但是有些地方我们需要改进一下。
第四步
- 每次都要启动2个进程岂不是很麻烦?
- 我想调试主进程的代码怎么办?
- 我不想使用默认的端口怎么办?
- 测试的时候使用的是localhost,打包的时候怎么办?
- 怎么打包?
- 怎么加一个icon?
- require('xxx')不起作用
这篇文章里用了foreman来管理进程,是个很聪明的方法,可以解决第1个问题,但是没办法解决第2个问题。如果Devtron还可以用的话,那么用foreman会是个非常好的方法,可惜Devtron这个项目不更新了。
其实前2个问题可以一起解决,就是使用VS Code:
假设你已经安装好了VS Code, "File >> Add Folder to Workspace",选择桌面上的dry文件夹。(dry=Do not Repeat Yourself)。
然后"Terminal >> Configure Default Build Task...",选择 "npm: start",会自动生成一个.vscode
文件夹和一个tasks.json
。
在type上面添加一行:"label": "antd",
(重要)
在group下面添加一行:"isBackground": true
。 (重要),
内容如下:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "antd",
"type": "npm",
"script": "start",
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true
}
]
}
VS Code运行的时候会一直等到task完成后才会启动electron。这是需要的,不然electron会启动失败。isBackground
的意思是让node 服务一直在后台运行。关闭electron后,netstat -ano | findstr 3000
你会看到node服务仍然在运行。
点击VS Code左侧"Debug(Ctrl+Shift+D)"按钮,然后点击"Configure or Fix 'launch.json'",选择"Node.js", 会自动生成一个launch.json。将这个文件的内容替换成:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
},
"args" : ["."],
"preLaunchTask": "antd"
}
]
}
点击"Start Debugging",你可以看到electron出来了。
在createWindow函数里打一个断点再次点击"Start Debugging",你会看到,程序在断点处停下来了。唿,小功告成。
现在来解决第3个问题。
再这之前你要把占用3000端口的进程杀掉。netstat -ano | findstr 3000
找到 pid 19420,
然后taskkill /pid 19420 -t -f
方法很简单,就是在运行npm run start
的时候设置环境变量PORT,将端口传进去。windows和*nix平台设置环境变量的方法不一样,为了跨平台我们需要安装一个包:
npm install cross-env --save-dev
将package.json里scripts的start命令替换成"start": "cross-env PORT=5000 react-app-rewired start"
。小功告成。
第4个问题
main.js
里添加2句:
const path = require('path')
const url = require('url')
并将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);
在package.json
里添加一句: "homepage": "./"
(非常非常重要)
如果不设置这个属性,编译后会输出如下信息,
The project was built assuming it is hosted at the server root.
You can control this with the homepage field in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
可以看看编译后的build/index.html里,PUBLIC_URL被替换成了"/", <link rel="manifest" href="/manifest.json">
打包后运行dry.exe只会显示一片空白。
react脚手架假设你的应用是放在web服务器的根目录或者子路径下的。这里设置 "homePage":"./"
,就表示我们的项目是放在当前目录。
设置这个以后,publicPath的值就是"./", 编译的时候会把这个传给webpack,打包后electron才能正确加载。
参考文档的PUBLIC_URL
在launch.json
里添加一句:
"env":{"ELECTRON_START_URL":"http://localhost:5000"}
你会看到现在的端口变成5000了,并且咱们的main.js能“感知”到是否是dev模式。
第5个问题
①先安装打包工具npm install electron-packager --save-dev
②然后编译 npm run build
, 会生成一个build文件夹,优化后的静态资源(html和js)都放在这里了。
③添加打包命令。很简单,直接从electron-api-demos的package.json拷贝一下就完事了。
稍作修改,我们生成64位的exe文件,并且将资源打包一下,文件输出路径为当前目录的output目录。指定exe的名称为dry。
在package.json的scripts里添加如下:
"package:win": "electron-packager ./ dry --out ./output --overwrite --asar=true --prune=true --platform=win32 --arch=x64",
④在dry文件夹下新建assets/app-icon/win目录,然后将准备好的app.ico文件放在这里
⑤执行npm run package:win
第6个问题
很简单,在“package:win”里加一句--icon=assets/app-icon/win/app.ico
。 ico文件可以用.png文件在线转。
第7个问题
在渲染进程里使用window.require
,比如:const mysql = window.require('mysql2');
,var ipcRenderer = window.require('electron').ipcRenderer;
参考大神的文章末尾
可能遇到的问题
如果你使用antd的脚手架,并且执行antd-init的时候报如下错误:
antd-init : 无法将“antd-init”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。,请确保环境变量Path里配置了全局包目录:D:\nodejs\node_global
为什么不用Photon或者React-Desktop?
2个我都试过了,效果并不好。尤其用photon,你可能需要require.js之类的来实现按需加载。绑定事件还得用原生的js来写。更麻烦的是以后没办法添加插件。
React-Desktop功能太少,不好用。而且它的Segmented Control组件的样式不好。做桌面小工具不需要菜单栏,这个时候Tab组件就非常重要,所以我放弃
React-Desktop了。
用antd是最爽的,文档清楚,组件丰富,可扩展性也强。