Electron学习指导
一、开始上手
1.1介绍
Electron = Chromium + Node.js + Native APIs
官方说:
Electron 是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS 和 Linux——不需要本地开发 经验。
大佬说:
Electron 是一个前端框架,可用于构建跨平台的桌面应用程序,桌面应用程序指的是可以在电脑上安装的软件(如QQ、浏览器、酷狗音乐、Skype、微信开发者工具、VS Code、Aotm、Postman等)。与 Java、C++ 等语言相同,前端技术也可用于桌面应用程序的开发。开发者可使用 JavaScript、HTML 和 CSS 等前端基础技术,结合 Node.js 进行开发。最重要的是,使用 Electron 开发的桌面应用程序,可以在 Windows、macOS 和 Linux 系统上无缝运行,实现跨平台开发。
我们可以使用 HTML 和 CSS 创建一个漂亮的用户界面,使用 JavaScript 处理用户输入和数据,使用 Node.js 处理系统调用和后台任务等等,使用 Electron 构建桌面应用程序就像在编写网页一样,相当容易上手。
我说:
要想Web应用变成桌面应用程序 ,就用前端技术写个 Web 应用,然后套上 Electron 这个外套,就变成了桌面应用程序。
优点:
- 跨平台支持:首先便是跨平台,Electron 框架可在主流的操作系统(例如 Windows、Mac OS 和 Linux 等)上运行,可以有效地减少开发者在不同平台上开发应用程序的工作量和时间。一套代码多平台运行,这点很重要。
- 前端技术支持:通过使用 HTML、CSS 和 JavaScript 等前端技术栈进行开发,拥有大量的UI组件和模板,开发出来的桌面应用界面更加美观、交互体验更好。
- 本地能力支持:Electron 除了支持 Web API,而且还允许调用很多操作系统底层 API 来访问计算机的硬件设备,甚至可以自己用 C++、Go 来编写本地模块,可以完成很多 Web 应用无法做到的事情。
- 调试测试支持:Electron 框架开发的应用程序是基于Chrome内核的,可以直接使用Chrome内核的开发者工具进行调试和测试,提高了开发效率。
- 自动更新支持:Electron 应用程序在发布后可以自动更新,这意味着当有新版本可用时,用户会自动收到更新提示,无需手动下载和安装更新文件。
缺点:
- 打包后的应用体积巨大:一个功能不算多的桌面应用,通过 electron-builder 压缩打包后至少也要 100MB。如果开发者不做额外的 Hack 工作的话,用户每次升级应用程序,还要再下载一次同样体积的安装包,这对于应用分发来说是一个不小的负担。但随着网络环境越来越好,用户磁盘的容积越来越大,此问题给用户带来的损失会慢慢被削弱。
- 开发复杂度较大:跨进程通信是基于 Electron 开发应用必须要了解的知识点,虽然 Electron 为渲染进程提供了 remote 模块来方便开发人员实现跨进程通信,但这也带来了很多问题,比如某个回调函数为什么没起作用、主进程为什么报了一连串的错误等,这往往给已经入门但需要进阶的开发者带来困惑。
- 安全性问题:Electron 把一些有安全隐患的模块和 API 都设置为默认不可用的状态,但这些模块和 API 都是非常常用的,因此有时开发者不得不打开这些开关。但是,一旦处理不当,就可能导致开发的应用存在安全隐患,给开发者乃至终端用户带来伤害。不过Electron 也有单独的一章讲述安全问题。
- 资源消耗较大:底层基于的 Chromium 浏览器一直以来都因资源占用较多被人诟病,目前来看这个问题还没有很好的解决办法,只能依赖 Chromium 团队的优化工作。
- 版本发布过快:为了跟上Chromium的版本发布节奏,Electron也有非常频繁的版本发布机制,每次 Chromium改动,都可能导致Electron出现很多新问题,甚至Electron的稳定版本都有很多未解决的问题
1.2快速体验
Electron Fiddle是Electron官方提供的快速演示或体验Electron API的工具,在Electron Fiddle内部集成了Electron的开发环境。通过该工具可以让开发者迅速体验Electron的某些新特性,对于初学者来说很友好
Electron项目代码
- index.html是项目的布局结构
- style.css是项目布局样式
- renderer.js是运行在浏览器环境(渲染进程)
- preload.js是运行在浏览器环境
- main.js是运行在Node环境
**注:**默认情况下每次打开Electron Fiddle都会重新的生成项目模板,代码模板可以以链接形式进行分享。
1.3从零开始
1.3.1、项目结构,Electron项目至少需要3个文件
- index.html
- package.json(npm init -y)
- main.js(习惯叫做main.js)
创建一个空白目录,然后分别创建上述3个文件
1.3.2、安装Electron依赖
因为Electron依赖于Nodejs。
**注:**二者有版本要求,比如Electron的v25.0.1版本就要求nodejs必须大于等于18.15.0版本。
参考对应版本 Electron Releases
#安装 electron
npm install electron --save-dev
检测是否成功
npm config list
1.3.3、修改package.json文件
"scripts": {
"start": "electron ."
}
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^18.1.0"
}
}
1.3.4、创建main.js文件
// electron 主进程
const {app, BrowserWindow} = require('electron');
// 处理路径
const path = require('path')
// 保持对window对象的全局引用,如果不这么做的话,当JS对象被垃圾回收的时候,window对象将会自动的关闭
let win;
// 创建应用窗口
function createWindow() {
// 实例化应用窗口。
win = new BrowserWindow({
width: 800,
height: 600,
titleBarStyle: 'hidden',
titleBarOverlay: true, // win 专用
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: true,
},
});
// 加载一个页面
win.loadFile('./index.html');
// win.loadURL('https://blog.51cto.com/u_16213320/8719454');
// 打开开发者工具
// win.webContents.openDevTools();
// 当 window 被关闭,这个事件会被触发。
win.on('closed', () => {
// 取消引用 window 对象,如果你的应用支持多窗口的话,
// 通常会把多个 window 对象存放在一个数组里面,
// 与此同时,你应该删除相应的元素。
win = null;
});
}
// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow);
// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
// 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
// 否则绝大部分应用及其菜单栏会保持激活。
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 在macOS上,当单击dock图标并且没有其他窗口打开时,
// 通常在应用程序中重新创建一个窗口。
if (win === null) {
createWindow();
}
});
// 在这个文件中,你可以续写应用剩下主进程代码。
// 也可以拆分成几个文件,然后用 require 导入。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
抽离目录写法:
// 热加载 用于修改完直接看效果
npm install --save-dev electron-reloader
const { app,BrowserWindow} = require('electron')
// 开启热加载
const reloader = require('electron-reloader')
reloader(module)
app.on('ready',()=>{
// 新建窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600
});
// 让主窗口加载文件 html文件
mainWindow.loadFile('./index.html');
// 引入自定义菜单
require('./menu')
})
menu.js
const { BrowserWindow, Menu } = require('electron')
// 配置模板
const template = [
{
label: '文件',
submenu: [
{
label: '新建窗口',
click() {
new BrowserWindow({
width: 300,
height: 200,
})
},
},
{
label: '保存',
},
{
label: '另存为',
},
{
label: '首选项',
},
{
label: '退出',
},
],
},
{
label: '编辑',
},
{
label: '关于我们',
},
]
// 菜单对象构建该模板,生成菜单对象
const menu = Menu.buildFromTemplate(template)
// 设置我们构建好的菜单
Menu.setApplicationMenu(menu)
1.3.5、启动预览窗口
npm run start
二、基本概念
2.1主进程(node)
2.1.1、BroswerWindow用来创建并按制浏览器窗口
- width/height指定窗口大小
- titleBarStyle窗口标题栏样式
- titleBarOverlay定义windows的标题栏
- loadFile实例方法,加载本地html文件
- loadURL实例方法,加载网络地址
2.1.2、app控制应用程序的事件生命周期
- ready在Election完成初始化时触发的生命周期
- active在Electron被激活(前台运行)时触发该生命周期
**注:**修改主进程后代码需要重启应用,快捷键Ctrl+C (win 按两次)
2.2渲染器进程
2.2.1、主进程中 (main.ts)
import { app, BrowserWindow, ipcMain } from 'electron';
app.on('ready', () => {
const mainWindow = new BrowserWindow();
ipcMain.handle('sumNumbers', async (event, num1: number, num2: number) => {
return num1 + num2;
});
});
2.2.2、渲染进程中 (renderer.ts)
import { ipcRenderer } from 'electron';
async function sumNumbers(num1: number, num2: number) {
try {
const result = await ipcRenderer.invoke('sumNumbers', num1, num2);
console.log('Result:', result); // 输出 8
} catch (error) {
console.error('Error:', error);
}
}
sumNumbers(5, 3);
2.3打包应用
当所有功能开发完毕后,将Electron打包成不同平台的应用,Electron提供了打包工具Electron Forge
,但实际应用中大家用的比较多的是electron-builder
。
2.3.1安装
npm install electron-builder --save-dev
2.3.2配置脚本
{
...
"scripts": {
"start": "electron .",
"build:mac": "electron-builder --mac",
"build:win": "electron-builder --win",
},
...
}
2.3.3生成图标
在项目根目录中创建build目录,在准备一张png格式的图片,将其命名为icon.png放到build中,关于图标
2.3.4执行打包任务
# 打包mac 系统的应用
npm run build:mac
# 打包win系统的应用
npm run build:win
注意:windows系统开发不能打包mac
三、项目开发
3.1创建项目(electron-vite)
前提条件
electron-vite 需要 Node.js 版本 18+,20+ 和 Vite 版本 4.0+
npm i electron-vite -D
搭建第一个 electron-vite 项目
npm create @quick-start/electron@latest
yarn create @quick-start/electron
pnpm create @quick-start/electron
然后按照提示操作即可!
✔ Project name: … <electron-app>
✔ Select a framework: › vue
✔ Add TypeScript? … No / Yes
✔ Add Electron updater plugin? … No / Yes
✔ Enable Electron download mirror proxy? … No / Yes
Scaffolding project in ./<electron-app>...
Done.
你还可以通过附加的命令行选项直接指定项目名称和你想要使用的模板。例如,要构建一个 Electron + Vue 项目,运行:
# npm 6.x
npm create @quick-start/electron my-app --template vue
# npm 7+, extra double-dash is needed:
npm create @quick-start/electron my-app -- --template vue
# yarn
yarn create @quick-start/electron my-app --template vue
# pnpm
pnpm create @quick-start/electron my-app --template vue
了解更多有关 create-electron 的信息。
3.2项目结构
main目录对应是的主进程代码
renderer目录对应的是渲染进程的代码,eg:Vue
preload目录对应的是预加脚本的代码
3.3打包应用
将准备好的图片放到build目录中,然后npm run build:mac
或npm run build:win
#没有- 默认打包本机 下面表示打包mac和win
"build": "electron-builder -mw"