electron-PC端多端融合方案

发表于 3年以前  | 总阅读数:1266 次

每天都要写第二天的 todoList。有一天在写的时候突然想到,为了让自己清楚知道自己需要做啥、做了多少、还剩多少没做,想写一个电脑端程序,在技术选型的时候就选了 electron。

一、 方案选型

3天时间写了个 PC 端应用程序。先看看结果吧

为什么要选 electron 作为 pc 端开发方案?

史前时代,以 MFC 为代表的技术栈,开发效率较低,维护成本高。

后来使用 QT 技术,特点是使用 DirectUI + 面向对象 + XML 定义 UI,适用于小型软件、性能要求、包大小、UI 复杂度叫高的需求。

再到后来,以 QT Quick 为代表的技术,特点是框架本身提供子控件,基于子控件组合来创建新的控件。类似于 ActionScript 的脚本化界面逻辑代码。

新时代主要是以 electron 和 Cef 为 代表。特点是界面开发以 Web 技术为主,部分逻辑需要 Native 代码实现。大家都熟悉的 VS Code 就是使用 electron 开发的。适用于 UI 变化较多、体积限制不大、开发效率高的场景。

拿 C 系列写应用程序的体验不好,累到奔溃。再加上有 Hybrid、React Native、iOS、Vue、React 等开发经验,electron 是不二选择。

二、 Quick start

执行下面命令快速体验 Hello world,也是官方给的一个 Demo。

git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install && npm start

简单介绍下 Demo 工程,工程目录如下所示

在终端执行 npm start 执行的是 package.json 中的 scripts 节点下的 start 命令,也就是 electron .. 代表执行 main.js 中的逻辑。

// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', function () {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

写过 Vue、React、Native 的人看代码很容易,因为应用程序的生命周期钩子函数是很重要的,开发者根据需求在钩子函数里面做相应的视图创建、初始化、销毁对象等等。比如 electron 中的 activate、window-all-closed 等。

app 对象在 whenReady 的时候执行 createWindow 方法。内部创建了一个 BrowserWindow 对象,指定了大小和功能设置(webPreferences Object (可选) - 网页功能的设置。其中 preload String (可选) - 在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。当 node integration 关闭时, 预加载的脚本将从全局范围重新引入 node 的全局引用标志)。

mainWindow.loadFile('index.html') 加载了同级目录下的 index.html 文件。也可以加载服务器资源(部署好的网页),比如 win.loadURL('https://github.com/FantasticLBP')

// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }
  console.table(process)
  console.info(process.versions)
  for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
  }
})

接下去看看 preload.js。在页面运行其他脚本之前预先加载指定的脚本,无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。Demo 中的逻辑很简单,就是读取 process.versions 对象中的 node、chrome、electron 的版本信息并展示出来。

index.html 中的内容就是主页面显示的内容。

三、 实现原理

electron 分为渲染进程和主进程。 和 Native 中的概念不一样的是 electron 中主进程只有一个,渲染进程(也就是 UI 进程) 有多个。主进程在后台运行,每次打开一个界面,会新开一个新的渲染进程。

• 渲染进程:用户看到的 web 界面就是由渲染进程绘制出来的,包括 html、css、js。

• 主进程:electron 运行 package.json 中的 main.js 脚本的进程被称为主进程。在主进程中运行的脚本通过创建 web 页面来展示用户界面。一个 electron 应用程序总是只有一个主进程。

1. Chromium 架构

这张图是 chromium 多进程架构图。早在2007年之前,市面上的浏览器都是单进程架构。单进程浏览器指的是浏览器的所有功能模块都是运行在同一个进程里的,这些模块包括网络、插件、Javascript 运行环境、渲染引擎和页面等。如此复杂的功能都在一个进程内运行,所以导致浏览器出现不稳定、不安全、不流畅等问题。

多进程架构的浏览器解决了上述问题,至于如何解决的以后的文章会专门讲解,不是本文的主要内容。

简单描述下。

• 主进程中的 RenderProcessHost 和 render 进程中的 RenderProcess 是用来处理进程间通信的(IPC)。

• Render 进程中的 RenderView 内容基于 WebKit 排版展示出来的

• Render 进程中的 ResourceDispatcher 是用来处理资源请求的。Render 进程中如果有请求则创建一个请求 ID,转发到 IPC,由 Browser 进程中处理后返回

• Chromium 是多进程架构,包括一个主进程,多个渲染进程

对于 chromium 多进程架构感兴趣的可以点击这个链接查看更多资料-Multi-process Architecture。

2. Electron 架构

Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲染进程。但是也有区别

• 在各个进行中暴露了 Native API ,提供了 Native 能力。

• 引入了 Node.js,所以可以使用 Node 的能力

技术难点:由于 Electron 内部整合了 Chromium 和 Node.js,主线程在某个时刻只可以执行一个事件循环,但是2者的事件循环机制不一样,Node.js 的事件循环基于 libuv,但是 Chromium 基于 message bump。

所以 Electron 原理的重点就是「如何整合事件循环」。2种思路

• Chromium 集成到 Node.js 中:用 libuv 实现 messagebump(Node-Webkit 就是这么干的,缺点挺多)

• Node.js 集成到 Chromium 中(Electron 所采用的方式)

后来随着 libuv 引入 backend_fd 的概念,相当于是 libuv 轮询事件的文件描述符。通过轮训 backend_fd 可以知道 libuv 的新事件。所以 Electron 采取的做法就是将 Node.js 集成到 Chromium 中。

上图描述了 Node.js 如何融入到 Chromium 中。描述下原理

• Electron 新起一个安全线程去轮训 backend_fd

• 当检测到一个新的 backend_fd,也就是一个新的 Node.js 事件之后,通过 PostTask 转发到 Chromium 的事件循环中

上述2个步骤完成了 Electron 的事件循环。

四、 如何调试

调试分为主进程调试和渲染进程调试。

1. 渲染进程调试

看到 Demo 工程中执行 npm start 之后可以看到主界面,Mac 端快捷键 comand + option + i,唤出调试界面,类似于 chrome 下的 devtools。其实就是无头浏览器的那些东西。或者在代码里打开调试模式 mainWindow.webContents.openDevTools()

工程采用 Electron + Vue 技术,下面截图 Vue-devtools 很方便查看 Vue 组件层级等 Vue 相关的调试

2. 主进程调试方式

主进程调试有2种方法

方法一:利用 chrome inspect 功能进行调试

• 需要在启动的时候给 package.json 中的 scripts 节点下的 start 命令加上调试开关

--inspect=[port]
// electrom --inspect=8001 yourApp

• 然后打开浏览器,在地址栏输入 chrome://inspect

• 点击 configure,在弹出的面板中填写需要调试的端口信息

• 重新开启服务 npm start,在 chrome inspect 面板的 Target 节点中选择需要调试的页面

• 在面板中可以看到主进程执行的 main.js。可以加断点进行调试

方法二:利用 VS Code 调试 electron 主进程。

• 在 VS Code 的左侧菜单栏,第四个功能模块就是调试,点击调试,弹出对话框让你添加调试配置文件 launch.json

• 编辑 launch.json 的文件内容。如下

 {
      "version": "0.2.0",
      "configurations": [
          {
              "type": "node",
              "request": "launch",
              "name": "Debug main process",
              "cwd": "${workspaceRoot}",
              "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
              "windows": {
                  "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
              },
              "args": ["."],
              "outputCapture": "std"
          }
      ]
  }

• 在调试模块电机绿色小三角,会运行程序,可以添加断点信息。整体界面如下所示。可以单步调试、可以暂停、鼠标移上去可以看到对象的各种信息。

3. 主进程调试之 hot reload

Electron 的渲染进程中的代码改变了,使用 Command + R 可以刷新,但是修改主进程中的代码则必须重新启动 yarn run dev 。效率低下,所以为了提升开发效率,有必要解决这个问题

Webpack 有一个 api: watch-run,可以针对代码文件检测,有变化则 Restart

五、 开发 tips

• 或许会为网页添加事件代码,但是页面看到的内容是渲染进程,所以事件相关的逻辑代码应该写在 html 引入的 render.js 中。

• 在 render.js 中写 Node 代码的时候需要在 main.js 初始化 BrowserWindow 的时候,在 webPreferences 节点下添加 nodeIntegration: true 。不然会报错:renderer.js:9 Uncaught ReferenceError: process is not defined。

• 从 Chrome Extenstion V2 开始,不允许执行任何 inline javascript 代码在 html 中。不支持以内联方式写事件绑定代码。比如 <button onclick="handleCPU">查看</button>

  Refused to execute inline event handler because it violates the following Content Security Policy directive:

• 利用 electron 进行开发的时候,可以看成是 NodeJS + chromium + Web 前端开发技术。NodeJS 拥有文件访问等后端能力,chromium 提供展示功能,以及网络能力(electron 网络能力不是 NodeJS 提供的,而是 chromium 的 net 模块提供的)。web 前端开发技术方案都可以应用在 electron 中,比如 Vue、React、Bootstrap、sass 等。

• 在工程化角度看,使用 yarn 比 npm 好一些,因为 yarn 会缓存已经安装过的依赖,其他项目只要发现存在缓存,则读取本地的包依赖,会更加快速。

• 在使用 Vue、React 开发 electron 应用时,可以使用 npm 或 yarn install 包,也可以使用 electron-vue 脚手架工具。

 vue init simulatedgreg/electron-vue my-project
   cd my-project
   npm install
   npm run dev

• 开发完毕后需要设置应用程序的图标信息、版本号等,打包需要指定不同的平台。

• 新开项目创建后会报错.

ERROR in Template execution failed: ReferenceError: process is not defined。解决办法是使用 nvm 将 node 版本将为 10。 ○ 报错如下

┏ Electron -------------------

[11000:0615/095124.922:ERROR:CONSOLE(7574)] "Extension server error: Object not found: <top>", source: chrome-devtools://devtools/bundled/inspector.js (7574)

┗ ----------------------------

解决办法是在 main/index.dev.js 修改代码

- require('electron-debug')({ showDevTools: true });
+ // NB: Don't open dev tools with this, it is causing the error
+ require('electron-debug')();

在 In main/index.js in the createWindow() function:

mainWindow.loadURL(winURL);
+  // Open dev tools initially when in development mode
+  if (process.env.NODE_ENV === "development") {
+    mainWindow.webContents.on("did-frame-finish-load", () => {
+      mainWindow.webContents.once("devtools-opened", () => {
+        mainWindow.focus();
+      });
+      mainWindow.webContents.openDevTools();
+    });
+  }

• Electron 多窗口与单窗口应用区别

• 知道 Electron 开发原理,所以大部分时间是在写前端代码。所以根据团队技术沉淀、选择对应的前端框架,比如 Vue、React、Angular。

• 也许开发并不难,难在视觉和 UX。很多写过网页的开发者或者以前端的视觉去写 Electron App 难免会写出网页版的桌面应用程序,说难听点,就是四不像 。所以需要转变想法,这是在开发桌面应用程序。

• Electron 和 Web 开发相比,各自有侧重点

六、 技术体系搭建

其实一个技术本身的难易程度并不是能否在自己企业、公司、团队内顺利使用的唯一标尺,其配套的 CI/CD、APM、埋点系统、发布更新、灰度测试等能否与现有的系统以较小成本融合才是很大的决定要素。因为某个技术并不是非常难,要是大多数开发者觉得很难,那它设计上就是失败的。

1. 构建

2. 工程解耦

3. 问题定位

Electron 提供的 crash 信息进行包装。

引申资料

• electron-vue架构解析-开发环境启动流程分析

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 目录