2022-04-29 | 使用指南 | UNLOCK | 更新时间:2022-11-25 10:3

Electronjs的入门及遇到的问题

Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用

使用须知

Electron 需要 node 的支持,文中举例,默认 yarn 和 node 是已经安装了,如果没有安装,请先安装后;

项目开启

# 创建文件夹并进入文件夹
mkdir demo && cd demo

# 初始化项目
yarn init -y

# 安装 electron
yarn add --dev electron

添加配置命令

package.json
... "main": "main.js", //入口文件 "scripts": { "start": "electron ." //启动命令 },

添加入口文件

index.html
<html> <head> <meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"> <title>Hello World!</title> </head> <body> <h1>Hello World!</h1> We are using Node.js <span id="node-version"></span>, Chromium <span id="chrome-version"></span>, and Electron <span id="electron-version"></span>. <p id="info"></p> <!-- 执行脚本,可以添加其他的执行脚本 --> <script src="./renderer.js"></script> </body> </html>
main.js
const { app, BrowserWindow } = require('electron') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) win.loadFile('index.html') } // 只有在app模块的ready事件被激发后才能创建浏览器窗口 app.whenReady().then(() => { createWindow() //通过调用createWindow app.on('activate', () => { // 在macOS上,当单击图标,并没有其他窗口打开 if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) // 监听关闭窗口,在所有窗口关闭后,退出 app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() })

在执行 yarn start 后,可以看到一个应用窗口被打开。

添加预加载脚本

为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为 预加载 的特殊脚本

preload.js
const { contextBridge } = require('electron'); contextBridge.exposeInMainWorld('versions', { node: () => process.versions.node, chrome: () => process.versions.chrome, electron: () => process.versions.electron, });

** 注意:如果发现报错提示contextBridge API can only **

main.js
// ... const path = require('path') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { // __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹) // path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串 preload: path.join(__dirname, 'preload.js') } }) win.loadFile('index.html') } // ...
index.html
<p id="info"></p> <script src="./renderer.js"></script> </body> </html>
renderer.js
const information = document.getElementById('info'); information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;

界面配置

界面设置,可以通过关闭所有菜单,然后自定义菜单去管理,也可以简单的通过预设菜单去管理

main.js
const { app, BrowserWindow ,Menu} = require('electron') // ... const template=[] //菜单为空 const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) const win = new BrowserWindow({ // ... // frame: false, //关闭所有菜单 // resizable: false, //界面缩放 // titleBarStyle: 'hidden', //隐藏边框 }) // 穿透窗口:忽略所有点击事件 win.setIgnoreMouseEvents(true)

调试模式

打开调试控制台 模式:right left bottom detach ; 关闭控制台 closeDevTools()

main.js
const { app, BrowserWindow } = require('electron') const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) + win.webContents.openDevTools({mode:'detach'}) win.loadFile('index.html') } // ...

优雅显示

  • ready-to-show

在项目第一次渲染的时候,可能会出现闪烁,可以通过设置 show:false ,在特定的时候显示出来

main.js
// ... const win = new BrowserWindow({ // ... show: false, //关闭显示 }) // 第一次完成绘制时,如果窗口还没有被显示,渲染进程会发出 ready-to-show 事件 win.once('ready-to-show', () => { win.show() }) ``` - backgroundColor 当项目过于复杂的时候,ready-to-show事件可能会比较缓慢,可以不使用 `ready-to-show` 简单的设置背景颜色就好了, 使用了 `ready-to-show` 也可以使用背景色,使应用更贴近原生 ```js main.js // ... const win = new BrowserWindow({ // ... backgroundColor: '#fff', //应用背景色 })

自动更新

update.electronjs.org

Electron 官方在 https://update.electronjs.org 上为开源应用程序提供了免费的自动更新服务。 使用它有以下几点要求:

  • 你的应用在 macOS 或 Windows 上运行
  • 你的应用有一个公开的 GitHub 仓库
  • 应用程序需要发布到 GitHub releases 中
  • 应用程序需要完成 签名

Electron-forge打包

# 安装 Electron Forge 打包脚手架. 并通过import自动化设置
yarn add --dev @electron-forge/cli
npx electron-forge import
# 自动配置后执行

# 打包命令
npm run package

# 配置分发资源 exe执行软件资产
npm run make

Electron-forge 配置

如果没有在 package.json文件中设置config.forge,Forge将尝试项目根目录中找到 forge.config.js文件.
可以在 package.json 中配置,也可以通过 forge.config.js 配置

  • package.json
package.json
{ "name": "my-app", "version": "0.0.1", "config": { "forge": { "packagerConfig": {}, "makers": [ { "name": "@electron-forge/maker-zip" } ] } } }
  • forge.config.js
forge.config.js
module.exports = { packagerConfig: {}, makers: [ { name: '@electron-forge/maker-zip' } ] }

配置图标

准备图标,MacOS:icns(512px x 512px) Linux:png(512px x 512px) Windows:ico(256px x 256px)

images/
├── icon.png
├── icon@2x.png
└── icon@3x.png

window 平台配置

forge.config.js
module.exports = { // ... config: { forge: { packagerConfig: { icon: '/path/to/icon' } } } }
main.js
const { BrowserWindow } = require('electron') const win = new BrowserWindow({ // ... icon: '/path/to/icon.png' })

问题

安装时间太长

国内的网络问题及安装地址的指向问题,导致国内安装的很慢

nrm use taobao
npm config edit
C:\Users\用户名\.npmrc
registry=https://registry.npmmirror.com/ // 在 registry 下添加指向地址 ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

资源被锁定或太忙 EBUSY: resource busy or locked

项目在运行导致安装失败,关闭执行中的项目在安装;

打包时候报错 Making a squirrel distributable for win32/x64

package.json 缺少必要字段 authors description

package.json
{ //... "authors": "xianbin", //作者 "description":"a electron demo", //描述 }

报错 contextBridge API can only be used when contextIsolation is enabled

需要启动 contextIsolation 才能对 contextIsolation 进行编程,从Electron12.0开始,会默认启用contextIsolation

main.js
// ... webPreferences: { contextIsolation: true, // __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹) preload: path.join(__dirname, 'preload.js') }

报错 require is not defined

需要在启动时候设置 contextIsolation 为 false

main.js
// ... webPreferences: { nodeIntegration: true, contextIsolation: false, // __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹) preload: path.join(__dirname, 'preload.js') }

警告 DevTools failed to load source map

打开控制台设置,将 Preferences => sources 中的 Enable tab moves focus 和 Enable CSS source maps 关闭。

警告 Electron Security Warning (Insecure Content-Security-Policy)

有两种解决方式,

1: 设置安全策略

index.html
... <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline';">

2: 屏蔽警告

main.js
// ... process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';