65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Electron 为 Windows on Arm 构建原生 WebView 应用程序

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2021 年 7 月 21 日

CPOL

7分钟阅读

viewsIcon

4912

downloadIcon

58

在本文中,我们将探讨如何创建针对 64 位 WoA 设备的全新 Electron 应用程序,以及如何移植现有的 Electron 应用程序。

引言

搭载 Arm 架构的 Windows (WoA) 设备,例如 Surface Pro X,可以通过模拟运行 x86 Windows 应用程序。通过 Insider 版本,WoA 设备还可以模拟为 x64 构建的 Windows 应用程序。模拟会将 x86 CPU 指令转换为 ARM 指令。当然,这不如原生运行应用程序(即直接为 ARM 架构和指令集编译)那样快——因此,如果您想利用平台的强大功能并最大限度地延长电池续航时间,您会希望创建原生应用程序。

有几种方法可以为 WoA 创建原生应用程序。例如,您可以创建针对 Arm 设备的通用 Windows 平台应用程序,如《当今 Windows 应用程序迁移的最佳实践》中所述。

创建可移植原生应用程序的另一种好方法是使用 WebView 框架,例如 CEF 或Electron。Electron 支持使用 Web 技术构建轻量级原生应用程序,从而轻松创建可移植到各种平台(包括 Arm 架构 Windows)的应用程序。借助 Electron,您可以使用 HTML、CSS 和 JavaScript 编写桌面应用程序,因为它允许您将 Web 应用程序嵌入到基于 Chromium 构建的原生应用程序 Shell 中。然后,您可以将生成的应用程序打包并分发为独立的应用程序。您还可以将 Electron 用作更广泛的原生应用程序的一部分。或者,您可以将其用于整个应用程序界面。一些完全基于 Electron 构建的知名应用程序是 Visual Studio Code 编辑器和 Slack 通信平台。

值得注意的是,您的打包应用程序会相当大,因为 Chromium 也会随之一起发布。此外,请考虑安全性可能是一个固有的挑战,因为 Chromium 会在 Electron 采用修复程序之前发布漏洞。

在本文中,我们将探讨如何创建针对 64 位 WoA 设备的全新 Electron 应用程序,以及如何移植现有的 Electron 应用程序。

一个新的 Electron 应用程序

作为演示,我们创建一个针对搭载 64 位 Arm Cortex-A (Aarch64) CPU 的 Windows 设备的新 Electron 应用程序,但它是在 x86-64 Windows 机器上构建的。首先,我们必须安装 Node.jsGit。(Git 是我们在此演示中使用的 electron-forge 打包器的依赖项。)

我们首先为 Electron 应用程序创建一个新目录,并使用 npm 初始化它

mkdir electron-arm
cd electron-arm
npm init -y

然后我们设置 npm_config_arch 环境变量,告诉 npm 我们希望下载依赖项的 Arch64 版本。在这种情况下,npm 将架构命名为 arm64

set npm_config_arch=arm64

注意:如果您使用的是 PowerShell,这将无法正确设置环境变量。您必须这样做

$env:npm_config_arch = 'arm64'

现在我们可以为我们的应用程序安装 electron 依赖项

npm install --save-dev electron

因为我们已经将架构设置为 arm64,所以 npm 已经将 Aarch64 版本安装到 node_modules 中。我们可以通过进入 node_modules\electron\dist 并尝试运行 electron.exe 来验证这一点。由于架构不匹配,应用程序应该无法运行。

如果您获得了一个成功的 Electron 窗口而不是此错误,则您安装了 x64 版本。在这种情况下,请删除 node_modules 目录,重新检查有关架构的先前步骤,然后重试 npm install

当然,因为我们安装了 Electron 的 Aarch64 版本,所以您将无法在您的 x64 机器上运行该应用程序。虽然这对于这个小型演示来说没有问题,但一般来说,您也会希望在您的开发机器上运行和测试您的应用程序。要在不同架构之间切换,请删除 node_modules 目录,按需要设置 npm_config_arch,然后运行 npm install

现在我们修改 package.json,将入口点更改为 main.js(而不是 index.js,作为 main 属性的值)和 author 属性的名称。此外,我们向 description 属性添加描述(这两个都是 electron-forge 的先决条件,我们将在本演示的后面部分使用它)。

...
"author": "Your Name",
"description": "Electron on WoA demo",
"main": "main.js",
...

我们使用的代码与 Electron 的快速入门指南中的 HTML 和脚本文件密切相关,但我们没有显示 Node.js、Chrome 和 Electron 的版本号,而是显示 CPU 架构(来自 process.arch 文件)。因此,现在我们的 main.js 文件与快速入门指南中的文件相同。在您的编辑器中创建文件 main.js,其内容如下:

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

function 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('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

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

然后创建 index.html,包含以下 HTML 文档

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Electron on WoA demo</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body style="background: white;">
    <p>
    Architecture: <span id="arch"></span>
    </p>
</body>
</html>

preload.js 中,我们用 process.arch 的内容填充 <span> 元素

window.addEventListener('DOMContentLoaded', () => {
  document.getElementById('arch').textContent = process.arch;
})

现在我们可以使用 electron-forge 将我们的应用程序打包为 Windows-on-Arm 设备。但首先,我们安装 electron-forge 作为依赖项并将其导入到应用程序文件夹中。

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

这会修改 package.json,为 electron-forge 添加额外信息,包括 package 和 make 脚本。

"package": "electron-forge package",
"make": "electron-forge make"

这意味着我们现在可以运行 npm run package(创建一个包含 Electron 应用程序及其所有必要资源文件的目录)。或者我们可以运行 npm run make(创建一个可分发的单个可执行文件)。然而,除非我们使用 —arch 标志另行指定,否则 Electron Forge 会使用我们开发机器的架构。我们在 package.jsonscripts 属性中添加另外两个值,以便将应用程序打包为 arm64,以及 package 和 make。

"scripts": {
  "start": "electron-forge start",
  "package": "electron-forge package",
  "make": "electron-forge make",
  "package-arm": "electron-forge package --arch=arm64",
  "make-arm": "electron-forge make --arch=arm64"
}

然后我们执行

npm run make-arm

在 out 目录中,我们可以看到打包后的应用程序位于 electron-arm-win32-arm64(名称取决于 package.json 中的 name 属性)和一个可分发的安装程序可执行文件位于 make\squirrel.windows\arm64。如果我们尝试在开发机器上运行它们,它们将无法工作。我们会遇到与尝试运行 Aarch64 electron.exe 文件类似的错误。但是,如果我们将包或设置文件放在 Windows on Arm 设备上,它们将正常工作。

如果您在 Arm 设备上运行我们的应用程序,您会看到

如您所见,应用程序正在 Arm 设备上原生运行。作为比较,我们可以尝试为 ia32 架构(即 x86)而不是 arm64 架构(即 Aarch64)打包应用程序。如果我们在 Arm 设备上运行它,我们会看到以下内容,表明它正在使用模拟

移植现有应用程序

假设我们已经编写了一个 Electron 应用程序,现在我们想将其移植到 Arm 架构的 Windows 上。再假设我们的应用程序没有使用任何原生模块。在这种情况下,我们删除 node_modules 文件夹,然后按照上一节的步骤操作:将 npm_config_arch 设置为 arm64,重新安装依赖项,然后打包应用程序。我们必须小心基于 process.arch 的 if 语句,因为它的值现在也可以是 arm64

如果我们有原生模块(并且假设我们已经在使用 Visual Studio 2019 并安装了 Desktop development with C++ 工作负载),我们必须安装用于 MSVC 的 C++ 构建工具。本教程使用 Visual Studio 2019 版本 16.9.31313.79,但这些步骤应该适用于 Visual Studio 2019 的任何版本。

使用 Visual Studio 安装程序,选择我们安装的修改,导航到“单个组件”,然后查找 MSVC v142 - VS 2019 C++ ARM64 构建工具(最新)。然后安装该组件。

一旦我们完成了这些,一切都像以前一样简单。当我们打包应用程序时,Electron Forge 会编译我们的原生模块,如果我们安装了 ARM64 构建工具,它就可以很好地为 Aarch64 CPU 目标进行交叉编译。

如果您没有带原生模块的应用程序,但仍然想尝试一下,您可以修改前面的演示应用程序以包含 microtime 作为依赖项。Microtime 是一个用于获取当前微秒时间的原生模块。然后我们更新 index.html 和 preload.js 以在窗口中显示 microtime.now 函数的值。例如,可以将此元素添加到 index.html 中:

<a><p>
  Microtime: <span id="microtime"></span>
</p></a>

preload.js 可以包含以下代码以定期更新元素

<a>const microtime = require('microtime');

window.addEventListener('DOMContentLoaded', () => {
  setInterval(() => {
    document.getElementById('microtime').textContent = microtime.now();
  }, 500);
})</a>

我们确保已安装 Visual Studio 2019,并包含 Desktop development with C++ 工作负载和 MSVC v142 - VS 2019 C++ ARM64 构建工具(最新)组件。然后我们尝试像之前的演示中一样使用 Electron Forge 打包应用程序,并在我们的 Arm 架构 Windows 设备上运行它。

结论和后续步骤

为了充分利用 Arm 架构的 Windows 平台,您需要为 ARM 架构原生创建应用程序。使用 Electron 框架可以轻松完成此操作。它只需要更改一些配置设置并为原生模块安装工具集。现在您已经知道如何为 WoA 编写原生 Electron 应用程序,请在您自己的应用程序中尝试一下。

如果您有兴趣进一步阅读,请参阅这些文章

© . All rights reserved.