Electron:从环境搭建到打包分发一个Electron应用

Electron:从环境搭建到打包分发一个Electron应用

在公司遇到一个小需求,需要了解一下Electron,所以来学习一下。

1.基本要求

安装 Node.js,建议使用最新的LTS版本(学习的话,真的都建议使用最新的稳定版本,等到熟悉了,在尝试切换版本,否则可能遇到很多问题)。下载地址:下载 使用平台预构建的 Node.js 安装器来进行安装, 否则,可能会遇到与不同开发工具不兼容的问题。查看node和npm(Node Package Management)版本是否安装正确:

node -v
npm -v

1675402252212

因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运行的 Node.js 版本无关。

因为npm的服务器在国外,所以经常遇到下载失败的问题,所以安装cnpm,并将包的下载地址切换到国内的淘宝镜像。具体步骤参看:npm 和 cnpm 的区别

cnpm和npm的使用方法完全一致,只是执行命令时将npm改成cnpm

2.HelloWord工程

1.使用脚手架搭建

1.Electron 应用程序遵循与其他 Node.js 项目相同的结构。 首先创建一个文件夹并初始化 npm 包。新建ElectronHelloWord目录,并使用npm init命令初始化。

npm init

1675402870273

具体参数设置参看:使用package.json (入门) - npm 中文开发手册

然后我们就可以在目录下看到生成的package.json文件

1675403081114

{
  "name": "electronhelloword",
  "version": "1.0.0",
  "description": "HelloWord",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron ."
  },
  "author": "Mr.WildFire",
  "license": "MIT",
  "devDependencies": {
    "electron": "^22.2.0"
  }
}

2.将 electron 包安装到应用的开发依赖中。

cnpm install --save-dev electron

1675403314391

3.在 package.json配置文件中的scripts字段下增加一条start命令:

{
  "scripts": {
    "start": "electron ."
  }
}

因为package.json是JSON文件,所以修改的时候要注意文件格式

4.start命令能在开发模式下打开应用

npm start

此脚本将告诉 Electron 在您项目根目录运行。此时,应用将立即抛出一个错误提示您它无法找到要运行的应用

1675403582041

2.运行主进程

任何 Electron 应用程序的入口都是 main 文件。 这个文件控制了主进程,它运行在一个完整的Node.js环境中,负责控制您应用的生命周期,显示原生界面,执行特殊操作并管理渲染器进程。执行期间,Electron 将依据应用中 package.json配置下main字段中配置的值查找此文件。

因为我们创建项目的时候main字段对应的文件是index.js要初始化这个main文件,需要在项目的根目录下创建一个名为index.js的空文件。如果此时再次运行start命令,应用将不再抛出任何错误! 当然,它不会做任何事因为我们还没有在index.js中添加任何代码。

1675403925071

3.创建页面

在可以为我们的应用创建窗口前,需要先创建加载进该窗口的内容。 在Electron中,各个窗口显示的内容可以是本地HTML文件,也可以是一个远程url

以本地HTML文件为例,在根目录下创建一个名为index.html的文件。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello Word!</title>
  </head>
  <body>
    <h1>Electron</h1>
    我们正在使用 Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    和 Electron <span id="electron-version"></span>.
  </body>
</html>

在这个HTML文本中,可以发现主体文本中丢失了版本编号。 稍后将使用 JavaScript 动态插入它们。

4.在窗口中打开页面

有了一个页面,将它加载进应用窗口中。 要做到这一点,需要 两个Electron模块

  • app 模块,它控制应用程序的事件生命周期。
  • BrowserWindow 模块,它创建和管理应用程序窗口。

因为主进程运行着 Node.js,您可以在 index.js 文件头部将它们导入作为 CommonJS 模块:

const { app, BrowserWindow } = require('electron')

然后,添加一个createWindow()方法来将index.html加载进一个新的BrowserWindow实例。

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

接着,调用createWindow()函数来打开您的窗口。

在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。 您可以通过使用 app.whenReady() API来监听此事件。 在whenReady()成功后调用createWindow()

app.whenReady().then(() => {
  createWindow()
})

此时再次执行npm start命令即可看到窗口中的页面。

1675405172626

5.管理窗口的生命周期

虽然你现在可以打开一个浏览器窗口,但你还需要一些额外的模板代码使其看起来更像是各平台原生的。 应用程序窗口在每个OS下有不同的行为,Electron将在app中实现这些约定的责任交给开发者们。一般而言,你可以使用 进程 全局的 platform 属性来专门为某些操作系统运行代码。

1.关闭所有窗口时退出应用 (Windows & Linux)

在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。为了实现这一点,你需要监听 app 模块的 'window-all-closed' 事件。如果用户不是在 macOS(darwin) 上运行程序,则调用 app.quit()

在index.js中添加:

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

2.如果没有窗口打开则打开一个窗口 (macOS)

当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。

为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。 通过在您现有的 whenReady() 回调中附上您的事件监听器来完成这个操作。

在index.js中添加:

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

6.通过预加载脚本从渲染器访问Node.js

最后要做的是输出Electron的版本号和它的依赖项到你的web页面上。

在主进程通过Node的全局 process 对象访问这个信息是微不足道的。 然而,你不能直接在主进程中编辑DOM,因为它无法访问渲染器 文档 上下文。 它们存在于完全不同的进程!如果想更多的了解Electron进程,参看:流程模型 | Electron (electronjs.org)

这是将 预加载 脚本连接到渲染器时派上用场的地方。 预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 windowdocument) 和 Node.js 环境。

创建一个名为preload.js的新脚本:

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})

上面的代码访问 Node.js process.versions 对象,并运行一个基本的 replaceText 辅助函数将版本号插入到 HTML 文档中。

要将此脚本附加到渲染器流程,请在你现有的 BrowserWindow 构造器中将路径中的预加载脚本传入 webPreferences.preload 选项。修改index.js为:

const { app, BrowserWindow } = require('electron')
// 在开头引入Node.js的'path'模块
const path = require('path')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

这里使用了两个Node.js概念:

  • __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)。
  • path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。

使用一个相对当前正在执行JavaScript文件的路径,这样的相对路径将在开发模式和打包模式中都将有效。

额外:将功能添加到您的网页内容

对于与网页内容的任何交互,想要将脚本添加到渲染器进程中。 由于渲染器运行在正常的 Web 环境中,因此可以在 index.html 文件关闭 </body> 标签之前添加一个 <script> 标签,来包括您想要的任意脚本:

<script src="./renderer.js"></script>

renderer.js 中包含的代码可以在接下来使用与前端开发相同的 JavaScript API 和工具。例如使用 webpack 打包并最小化您的代码,或者使用 React 来管理您的用户界面。

总结

最后,得到了一个功能齐全的Electron的HelloWordDemo应用

1675408463486

Windows上 ctrl+shift+i 打开开发界面。

总结我们所做的所有步骤:

  • 我们启动了一个Node.js程序,并将Electron添加为依赖。
  • 我们创建了一个 main.js 脚本来运行我们的主要进程,它控制我们的应用程序 并且在 Node.js 环境中运行。 在此脚本中, 我们使用 Electron 的 appBrowserWindow 模块来创建一个浏览器窗口,在一个单独的进程(渲染器)中显示网页内容。
  • 为了访问渲染器中的Node.js的某些功能,我们在 BrowserWindow 的构造函数上附加了一个预加载脚本。

代码库如下:

3.打包分发应用程序

最快捷的打包方式是使用 Electron Forge

1.将 Electron Forge 添加到应用的开发依赖中,并使用其"import"命令设置 Forge 的脚手架:

cnpm install --save-dev @electron-forge/cli
npx electron-forge import

1675407564761

2.使用Forge 的 make 命令来创建可分发的应用程序:

1675407716321

Electron-forge 会创建 out 文件夹,软件包将在那里找到。

1675407827697

参考文档和源代码

参考文档:Electron官方文档快速入门 | Electron (electronjs.org)

参考源代码:Electron_HelloWord: Electron_HelloWord (gitee.com)

posted @ 2023-02-03 17:56  Mr_WildFire  阅读(513)  评论(0编辑  收藏  举报