electron开发桌面应用入门
文章目录
- 入门
- 开发调试
- 预加载脚本
- 打包,使用Electron Forge工具
- 相关问题
- 为什么要打包所有Chromium
- Electron 不使用您系统的 Node.js 环境来运行它的代码
入门
nvm use 20.19.2
npm install electron --save-dev
为什么 Electron 是 devDependency?
实际上,打包后的应用本身会包含 Electron 的二进制文件,因此不需要将 Electron 作为生产环境依赖。
{"name": "my-electron-app","version": "1.0.0","description": "Hello World!","main": "main.js","scripts": {"start": "electron .","test": "echo \"Error: no test specified\" && exit 1"},"author": "Jane Doe","license": "MIT","devDependencies": {"electron": "23.1.3"}
}
上面 main 中配置的入口文件 man.js
console.log('Hello from Electron 👋')
const { app, BrowserWindow } = require('electron/main')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600})win.loadFile('index.html')
}
// 如果没有窗口打开则打开一个窗口 (macOS)
app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}})
})
// 关闭所有窗口时退出应用 (Windows & Linux)
app.on('window-all-closed', () => {// 环境变量 win32 (Windows), linux (Linux) 和 darwin (macOS) // 通过检查 Node.js 的 process.platform 变量,您可以针对特定平台运行特定代码。https://nodejs.org/api/process.html#process_process_platformif (process.platform !== 'darwin') {app.quit()}
})
上面中 win.loadFile(‘index.html’) 中的 index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --><metahttp-equiv="Content-Security-Policy"content="default-src 'self'; script-src 'self'"/><metahttp-equiv="X-Content-Security-Policy"content="default-src 'self'; script-src 'self'"/><title>Hello from Electron renderer!</title></head><body><h1>Hello from Electron renderer!</h1><p>👋</p></body>
</html>
启动项目
npm run start
因为 Electron 的主进程就是一个 Node.js 运行时,所以你可以直接用 electron 命令运行任意的 Node.js 代码
将网页装载到 BrowserWindow
您应用中的每个页面都在一个单独的进程中运行,我们称这些进程为 渲染器 (renderer)
正常点左上角 X 关闭其实是最小化,和我们平常 mac 使用一样
开发调试
预加载脚本
预加载脚本包含在浏览器窗口加载网页之前运行的代码。 其可访问 DOM 接口和 Node.js 环境,并且经常在其中使用 contextBridge 接口将特权接口暴露给渲染器。
举例:将脚本注入到网页中使用
main.js
const path = require('node:path')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,// 注入脚本preload.jswebPreferences: {preload: path.join(__dirname, 'preload.js')}})win.loadFile('index.html')
}
preload.js
const { contextBridge } = require('electron/renderer')// 由 node 导出 version 这个对象给渲染器用
contextBridge.exposeInMainWorld('versions', {node: () => process.versions.node,chrome: () => process.versions.chrome,electron: () => process.versions.electron
})
renderer.js
const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${window.versions.chrome()}), Node.js (v${window.versions.node()}), and Electron (v${window.versions.electron()})`
index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><metahttp-equiv="Content-Security-Policy"content="default-src 'self'; script-src 'self'"/><metahttp-equiv="X-Content-Security-Policy"content="default-src 'self'; script-src 'self'"/><title>Hello from Electron renderer!</title></head><body><h1>Hello from Electron renderer!</h1><p>👋</p><p id="info"></p></body>引入后渲染到页面p标签上<script src="./renderer.js"></script>
</html>
打包,使用Electron Forge工具
npm install --save-dev @electron-forge/cli
npx electron-forge import
执行完以上命令,会发现
- package.json 安装了更多的包
- 新增了几个命令
- forge.config.js 文件
{"name": "my-electron-app","version": "1.0.0","description": "","main": "index.js","scripts": {"start": "electron-forge start","test": "echo \"Error: no test specified\" && exit 1","package": "electron-forge package","make": "electron-forge make"},"author": "","license": "ISC","devDependencies": {"@electron-forge/cli": "^7.8.2","@electron-forge/maker-deb": "^7.8.2","@electron-forge/maker-rpm": "^7.8.2","@electron-forge/maker-squirrel": "^7.8.2","@electron-forge/maker-zip": "^7.8.2","@electron-forge/plugin-auto-unpack-natives": "^7.8.2","@electron-forge/plugin-fuses": "^7.8.2","@electron/fuses": "^1.8.0","electron": "^37.2.4"},"dependencies": {"electron-squirrel-startup": "^1.0.1"},"packageManager": "pnpm@10.13.1+sha512.37ebf1a5c7a30d5fabe0c5df44ee8da4c965ca0c5af3dbab28c3a1681b70a256218d05c81c9c0dcf767ef6b8551eb5b960042b9ed4300c59242336377e01cfad"
}
forge.config.js
相关文档 https://www.electronforge.io/config/makers
const { FusesPlugin } = require('@electron-forge/plugin-fuses');
const { FuseV1Options, FuseVersion } = require('@electron/fuses');module.exports = {packagerConfig: {asar: true,},rebuildConfig: {},makers: [{name: '@electron-forge/maker-squirrel',config: {},},{name: '@electron-forge/maker-zip',platforms: ['darwin'],},{name: '@electron-forge/maker-deb',config: {},},{name: '@electron-forge/maker-rpm',config: {},},],plugins: [{name: '@electron-forge/plugin-auto-unpack-natives',config: {},},// Fuses are used to enable/disable various Electron functionality// at package time, before code signing the applicationnew FusesPlugin({version: FuseVersion.V1,[FuseV1Options.RunAsNode]: false,[FuseV1Options.EnableCookieEncryption]: true,[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,[FuseV1Options.EnableNodeCliInspectArguments]: false,[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,[FuseV1Options.OnlyLoadAppFromAsar]: true,}),],
};
执行打包,具体打包配置在 forge.config.js 中的 maker 字段
npm run make
# 同
DEBUG=electron-forge:* electron-forge make
- 它将首先运行 electron-forge package ,把您的应用程序 代码与 Electron 二进制包结合起来。 完成打包的代码将会被生成到一个特定的文件夹中。
- 然后它将使用这个文件夹为每个 maker 配置生成一个可分发文件。
相关问题
为什么要打包所有Chromium
既然大多数现代操作系统已经自带了浏览器和某种形式的 Web 视图,为什么我们还要将 Chromium 的 Web 堆栈打包进我们的应用程序?
稳定性: 现代 Web 技术栈非常复杂,因此,您迟早会遇到 bug。 如果您使用操作系统的 Web 视图,那么您唯一的解决办法就是让客户升级操作系统。 如果用户的机器无法升级(例如无法升级到最新的 macOS 或 Windows 11),您就不得不要求他们购买新电脑。 假如运气不好,您可能会因此失去一个主要客户,因为他们不可能仅仅为了让某个团队试用您初创公司的应用而升级数千台机器。 遇到这种情况,您将 无计可施 。 对于那些雇佣 Electron 维护者的公司来说,即使出现这种情况的风险也是无法接受的。
打包后的 Electron 应用通常约为 80 至 100MB。
Electron 不使用您系统的 Node.js 环境来运行它的代码
虽然您需要在开发环境安装 Node.js 才能编写 Electron 项目,但是 Electron 不使用您系统的 Node.js 环境来运行它的代码。 相反地,它使用它内置的 Node.js 运行时。 这意味着您的终端用户不需要 Node.js 环境也可以运行您的应用。
要查看您应用内置的 Node.js 版本,您可以访问主进程 (main process) 或预加载脚本 (preload script) 中的 process.versions 变量。 更多信息可以参考https://releases.electronjs.org/releases.json。