11 KiB
| title | date | draft | toc | tags | categories | images |
|---|---|---|---|---|---|---|
| 使用Electron+React开发跨平台桌面应用 | 2019-07-29T19:59:59+08:00 | false | true | [electron react] | web | [img/electron.png] |
使用Electron开发跨平台桌面应用,已经被越来越多的人接受。从开发者的角度,以前需要很多代码才能做到的自动布局、脏区裁剪、图像栅格化、GPU加速,现在通通不用管了,即使要处理,也是几行代码的事;从企业角度,前端开发人员众多,比较容易招聘,另外,资深前端相对于资深C++客户端,薪资还是有差距的,也节省了不少成本。本文主要着重说明使用Electron+React搭建开发环境的步骤。
技术栈
开发环境设置
创建一个新的React项目
npx create-react-app web-designer-test
cd web-designer-test
添加依赖库
yarn add electron wait-on concurrently --dev
yarn add electron-is-dev
- electron 用于界面开发的核心框架
- electron-builder 用于构建安装包
- wait-on concurrently 由于electron需要在react启动之后启动,所以增加这两个库用于同步进程启动顺序
- electron-is-dev 判断当前运行环境
创建文件public/main.js
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const isDev = require('electron-is-dev');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({width: 900, height: 680, webPreferences: {nodeIntegration: true}});
mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`);
if (isDev) {
// Open the DevTools.
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
mainWindow.webContents.openDevTools();
}
mainWindow.on('closed', () => mainWindow = null);
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
增加下面的命令到package.json文件中的scripts标签内
"electron-dev": "concurrently \"yarn start\" \"wait-on http://localhost:3000 && electron .\""
增加入口文件到package.json文件中
"main": "public/main.js"
到现在为止,package.json文件应该类似于下面这样
{
"name": "web-designer-test",
"version": "0.1.0",
"private": true,
"dependencies": {
"electron-is-dev": "^1.1.0",
"react": "^16.8.7",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1"
},
"main": "public/main.js",
"scripts": {
"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",
"eject": "react-scripts eject",
"electron-dev": "concurrently \"yarn start\" \"wait-on http://localhost:3000 && electron .\""
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"concurrently": "^4.1.1",
"electron": "^5.0.8",
"wait-on": "^3.3.0"
}
}
为了开发环境下,不启动默认浏览器,需要设置BROWSER环境变量,在根目录创建.env文件
BROWSER=non
这个时候可以使用下面命令运行程序
yarn electron-dev
如果在新的程序窗口内出现了React的欢迎页,则表示一切已经准备OK。但是现在JavaScript的运行环境是浏览器,无法访问宿主机的资源,比如读取文件或注册表,所以需要切换到Node.js环境,使用electron-renderer作为Webpack target,我们使用Rescripts来处理这个问题。
安装依赖库
yarn add @rescripts/cli @rescripts/rescript-env --dev
修改package.json文件中scripts标签内的启动脚本
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
修改为
"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",
在根目录新建文件.rescriptsrc.js
module.exports = [require.resolve('./.webpack.config.js')]
最后,在根目录新建另一个文件.webpack.config.js
// define child rescript
module.exports = config => {
config.target = 'electron-renderer';
return config;
}
现在就切换到了Node.js运行环境,可以随意访问主机资源了。
打包环境设置
首先,要添加依赖库
yarn add electron-builder --dev
CRA(Create Reactive Application)默认创建的index.html,会使用绝对路径来访问资源,在Electron中会加载资源失败,所以需要修改配置,在package.json中增加homepage属性
"homepage": "./",
接下来添加打包命令,在package.json中的scripts标签中
"postinstall": "electron-builder install-app-deps",
"preelectron-pack": "yarn build",
"electron-pack": "electron-builder -mw"
"postinstall": "electron-builder install-app-deps"用于确保本地依赖库都已经安装"preelectron-pack": "yarn build"会保证在打包前构建应用"electron-pack": "electron-builder -mw"会为Mac(m)和Windows(w)平台进行App打包
在执行打包命令前,还需要设置打包参数,在package.json中添加如下信息
"author": {
"name": "lniwn",
"email": "[email protected]",
"url": "https://oaoa.me"
},
"build": {
"appId": "me.oaoa.web-designer-test",
"productName": "WebDesignerTest",
"copyright": "Copyright © 2019 ${author}",
"mac": {
"category": "public.productivity.utilities"
},
"win": {
"icon": "assets/icon.png",
"target": "nsis"
},
"nsis": {
"allowToChangeInstallationDirectory": true,
"allowElevation": false,
"createDesktopShortcut": true,
"menuCategory": true,
"oneClick": false
},
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
}
}
可以在这里查看Electron Builder的所有选项。
创建一个assets文件夹,用于存放图片资源。
最好在一个平台只构建当前平台的可执行程序,这里针对Windows平台的构建进行了详细设置。
最终,package.json文件内容如下:
{
"name": "web-designer-test",
"version": "0.1.0",
"private": true,
"dependencies": {
"electron-is-dev": "^1.1.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1"
},
"main": "public/main.js",
"homepage": "./",
"description": "Web页面设计器",
"scripts": {
"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",
"eject": "react-scripts eject",
"electron-dev": "concurrently \"yarn start\" \"wait-on http://localhost:3000 && electron .\"",
"postinstall": "electron-builder install-app-deps",
"preelectron-pack": "yarn build",
"electron-pack": "electron-builder -mw",
"electron-pack-win": "electron-builder -c.extraMetadata.main=build/main.js --win --x64"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@rescripts/cli": "^0.0.11",
"@rescripts/rescript-env": "^0.0.10",
"concurrently": "^4.1.1",
"electron": "^5.0.8",
"electron-builder": "^21.1.5",
"wait-on": "^3.3.0"
},
"author": {
"name": "lniwn",
"email": "[email protected]",
"url": "https://oaoa.me"
},
"build": {
"appId": "me.oaoa.web-designer-test",
"productName": "WebDesignerTest",
"copyright": "Copyright © 2019 ${author}",
"mac": {
"category": "public.productivity.utilities"
},
"win": {
"icon": "assets/icon.png",
"target": "nsis"
},
"nsis": {
"allowToChangeInstallationDirectory": true,
"allowElevation": false,
"createDesktopShortcut": true,
"menuCategory": true,
"oneClick": false
},
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
}
}
}
由于Electron默认入口文件为build/Electron.js,如果想自定义,需要在参数中指定入口文件,否则编译会报错
"electron-pack-win": "electron-builder -c.extraMetadata.main=build/main.js --win --x64"
最后,执行打包命令
yarn electron-pack-win
会在dist文件夹下生成对应安装包
文件夹结构如下:
F:\Project\electron\web-designer-test
├.env
├.gitignore
├.rescriptsrc.js
├.webpack.config.js
├assets
│ ├icon.png
├build
│ ├asset-manifest.json
│ ├favicon.ico
│ ├index.html
│ ├main.js
│ ├manifest.json
│ ├precache-manifest.3ef21b1d6090801b808aaff5b52f1a17.js
│ ├service-worker.js
│ ├static
├dist
│ ├.icon-ico
│ ├builder-effective-config.yaml
│ ├WebDesignerTest Setup 0.1.0.exe
│ ├WebDesignerTest Setup 0.1.0.exe.blockmap
│ ├win-unpacked
├node_modules
├package.json
├public
│ ├favicon.ico
│ ├index.html
│ ├main.js
│ ├manifest.json
├README.md
├src
│ ├App.css
│ ├App.js
│ ├App.test.js
│ ├index.css
│ ├index.js
│ ├logo.svg
│ ├serviceWorker.js
├yarn.lock
开发笔记
填坑记录
-
启动报错
'require()' is not defined.从Electron 5.0版本开始,
nodeIntegration默认值由true改为false,具体可以参考官方文档,修改方式是在创建窗口时指定值为true即可。mainWindow = new BrowserWindow({width: 900, height: 680, webPreferences: {nodeIntegration: true}}); -
使用VSCode进行主进程调试
添加一个文件
.vscode/launch.json在项目根目录,然后即可使用VSCode进行调试。{ "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" : ["."], "outputCapture": "std" } ] }
参考文档*