记录工作中使用 electron + react 搭建桌面应用
------- 2023.3.1
1. 在使用 Electron 开发之前,需要安装node等环境
gogogo:
1. 使用脚手架创建一个 react 项目
这里可以看 react 的官网
npx create-react-app my-app
// 有一说一,react 创建项目是真的方便
cd my-app
// 有需要的童鞋,可以暴露下 webpack 配置,毕竟所有的操作自己把控还是比较舒心的
npm run eject
就是这么简单,以上就创建了一个简单的 react 项目
2. 安装 electron ,迎来今天de猪脚
# 安装 electron 包
npm i --save-dev electron
3. 运行主进程
在 Electron 应用程序得入口都是 main 文件,这个文件控制了 主进程,它运行在一个完整的 Node.js 环境中,负责控制应用的生命周期,显示原生界面,执行特殊操作并管理渲染进程。
这里缺少 main.js 文件,我们就创建一个
main.js
在react项目中,已经有了index.html页面,怎样才能把页面插入到 Electron 中呢?
这里需要两个模块:
- app 模块,控制应用程序的事件生命周期
- BrowserWindow 模块,创建和管理应用程序窗口
因为主进程运行着 Node.js,可以在 main.js 文件头部将他们导入作为 CommonJS模块
// app 模块,它控制应用程序的事件生命周期。
// BrowserWindow 模块,它创建和管理应用程序 窗口。
const {app, BrowserWindow} = require('electron');
然后,添加一个 createWindow() 方法,将 index.html 加载进一个新的 BrowserWindow 实例。
// 添加一个createWindow()方法来将index.html加载进一个新的BrowserWindow实例。
const createWindow = () => {
const win = new BrowserWindow({
width: 800,// 窗口宽度
height: 600 // 窗口高度
});
// 加载应用 --开发阶段 需要运行 npm run start
win.loadURL('http://localhost:3000/');
};
接着调用 createWindow() 来打开窗口
// 调用createWindow()函数来打开您的窗口。
// 在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。
// 您可以通过使用 app.whenReady() API来监听此事件。
// 在whenReady()成功后调用createWindow()。
app.whenReady().then(() => {
createWindow();
});
4. 管理窗口的生命周期
虽然现在可以打开一个浏览器窗口,但还需要一些额外的模板代码使其看起来更像是各个平台原生的。应用程序窗口在每个 OS 下有不同的行为,Electron 将在 app 中实现这些约定的责任交给开发者们。
4.1 关闭所有窗口时退出应用
在 window 和 Linux 上,关闭所有窗口通常会完全退出一个应用程序。
app.on('window-all-closed', ()=>{
// macOS(darwin)
if (process.platform !== 'darwin') app.quit();
})
4.2 如果没有窗口则打开一个窗口
当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
实现这个特性,则监听app模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
// 当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常在没有打开任何窗口的情况下也继续运行,
// 并且在没有窗口可用的情况下激活应用时会打开新的窗口。
// 实现这个特性,则监听app模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
// 因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件,在 whenReady() 回调中附上您的事件监听器来完成这个操作
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
这个时候,窗口的控件功能应该已经齐全
完整的 main.js 文件
/*
* @author: zhangning
* @date: 2023/3/2 9:59
* @Description: 创建 main.js 文件,配置 Electron
**/
// app 模块,它控制应用程序的事件生命周期。
// 事件调用app.on('eventName', callback),方法调用app.functionName(arg)
// BrowserWindow 模块,它创建和管理应用程序 窗口。
// new BrowserWindow([options]) 事件和方法调用同app
const {app, BrowserWindow, nativeImage} = require('electron');
// const url = require('url');
// const path = require('path');
// 添加一个createWindow()方法来将index.html加载进一个新的BrowserWindow实例。
const createWindow = () => {
let win = new BrowserWindow({
width: 800,// 窗口宽度
height: 600, // 窗口高度
title: 'Electron', // 窗口标题,如果由loadURL()加载的HTML文件中含有标签<title>,该属性可忽略
// "string" || nativeImage.createFromPath('src/image/icons/256x256.ico')从位于 path 的文件创建新的 NativeImage 实例
icon: nativeImage.createFromPath('src/public/favicon.ico'),
webPreferences: { // 网页功能设置
nodeIntegration: true, // 是否启用node集成 渲染进程的内容有访问node的能力
webviewTag: true, // 是否使用<webview>标签 在一个独立的 frame 和进程里显示外部 web 内容
webSecurity: false, // 禁用同源策略
nodeIntegrationInSubFrames: true // 是否允许在子页面(iframe)或子窗口(child window)中集成Node.js
}
});
// 加载应用 --开发阶段 需要运行 npm run start
win.loadURL('http://localhost:3000/');
// __dirname 字符串指向当前正在执行脚本的路径
// path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。
// win.loadURL(url.format({
// pathname: path.join(__dirname, './build/index.html'),
// protocol: 'file:',
// slashes: true
// }));
// 解决应用启动白屏问题
win.on('ready-to-show', () => {
win.show();
win.focus();
});
// 当窗口关闭时发出。在你收到这个事件后,你应该删除对窗口的引用,并避免再使用它。
win.on('closed', () => {
win = null;
});
};
// 调用createWindow()函数来打开您的窗口。
// 在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。
// 您可以通过使用 app.whenReady() API来监听此事件。
// 在whenReady()成功后调用createWindow()。
app.whenReady().then(() => {
createWindow();
// 当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常在没有打开任何窗口的情况下也继续运行,
// 并且在没有窗口可用的情况下激活应用时会打开新的窗口。
// 实现这个特性,则监听app模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
// 因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件,在 whenReady() 回调中附上您的事件监听器来完成这个操作
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// 关闭所有窗口时退出应用
// 在 window 和 Linux 上,关闭所有窗口通常会完全退出一个应用程序。
app.on('window-all-closed', () => {
// macOS(darwin)
if (process.platform !== 'darwin') app.quit();
});
2. 修改 package.json 文件
上面主进程文件创建完成了,这时候来修改 package.json 文件。主要是:
- 配置启动文件,添加 main 字段,也就是 main.js 文件,如果没有添加,Electron 将尝试加载包含 package.json 文件目录中的 index.js 文件。
- 配置运行命令 使用 "electron-start": "electron ."
{
"name": "zn-electron-app",
"version": "0.1.0",
"private": true,
"main": "electron/main.js",
"homepage": ".",
"dependencies": {
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"electron-start": "electron .",
"dev": "concurrently "npm run start" "npm run electron-start""
},
...
}
...
}
1. 启动 Electron
main.js 文件配置了 react 项目地址 mainWindow.loadURL('http://localhost:3000/'), 则需要启动 react 项目
# 启动 react 项目
npm start
# 启动 electron 项目
npm run electron-start
2. 可以看到上面配置了 dev ,就是合并运行的意思
2.1 安装 concurrently
npm install concurrently --save
2.2 编写 package.json
"dev": "concurrently "npm run start" "npm run electron-start""
2.3 执行 dev 命令
npm run dev
发现项目已经运行成功,(这也很 easy 吗!狗头)
后面继续更新 build 打包方面的配置