Electron框架是什么?

一、Electron是什么

Electron是一个能让你使用传统Web 前端技术(Nodejs, Javascript, HTML, CSS)开发一个跨平台桌面应用的框架。这里所说的桌面应用指的是在Windows、OSX及Linux系统上运行的程序。[1][2]

所谓的“集成框架”也就是它将“Chromium”和“Node.js”很好的集成在了一起,并明确分工,Electron负责硬件部分,“Chromium”和“Node.js”负责界面与逻辑,大家井井有条,共同构成了一个成本低廉却十分高效的解决方案。[3]

Electron 最初由赵成和 GitHub 的工程师于 2013 年4月创建,当时名字为 Atom Shell,用来服务于 GitHub 的开发工具 Atom,2014 年5月开源,2015 年4月才正式更名为 Electron。目前 GitHub 公司内部仍有一个团队在维护这个开源项目,且社区内也有很多的贡献者。[1]

Electron 更新非常频繁,平均一到两周就会有新版本发布,Issue 和 Pull request 的回复也非常及时,一般关系到应用崩溃的问题(Crash Issue)一两天就能得到回复,普通问题一周内也会有人跟进。社区活跃程度由此可见一斑。[1]

  • Electron的发展里程碑[2]

    • 2013年4月11日,Electron以Atom Shell为名起步。
    • 2014年5月6日,Atom以及Atom Shell以MIT许可证开源。
    • 2015年4月17日,Atom Shell改名为Electron。
    • 2016年5月11日,1.0版本发布。
    • 2016年5月20日,允许向Mac应用商店提交软件包。
    • 2016年8月2日,支持Windows商店。
  • Electron的内置功能

    • 自动更新 – 使应用程序能够自动更新、升级
    • 本机菜单和通知 – 创建本机应用程序菜单和上下文菜单
    • 应用程序崩溃报告 – 你可以将崩溃报告提交给远程服务器
    • 调试和分析 – Chromium的内容模块可以发现性能瓶颈和运行缓慢的原因。此外,你也可以在应用中使用自己喜欢的Chrome开发者工具
    • Windows安装程序 -你可以快速而简单创建安装包
  • 拓展——嵌入式浏览器[7]

    • 简单理解,嵌入式浏览器框架就是嵌入在客户端软件中的浏览器控件,浏览器与宿主程序是隔离的,通过浏览器控件的丰富接口可以使浏览器与宿主程序进行交互实现丰富的功能。说简单点就是用前端技术开发客户端界面

    • 常见的嵌入式浏览器框架:

      1. CEF(占有率世界第一)

      2. Electron

      3. QTwebkit

      4. bkit

      5. WebBrowser

二、Electron的构成

2.1 ‌‌Electron的基本文件结构[3]

‌‌Electron有一个基本的文件结构,类似于我们在创建网页时使用的文件结构[3]:

  • electron-quick-start

    • index.html 这是一个HTML5网页,目的用于提供画布(canvas)

    • main.js 创建窗口并处理系统事件

    • package.json 是我们应用程序的启动脚本。它将在主进程中运行,并包含有关应用程序的所有信息

    • render.js 处理应用程序的渲染过程

    • 其他

2.2 Electron的架构[3][8]

回顾以往的web开发,我们的代码,无论是HTML、CSS还是Javascript,都是运行在浏览器沙盒中的,我们无法越过浏览器的权限访问系统本身的资源,代码的能力被限制在了浏览器中。浏览器之所以这么做,是为了安全的考虑。

但我们要开发的是桌面应用程序,如果无法访问到本地的资源肯定是不行的。Electron将nodejs巧妙的融合了进来,让nodejs作为整个程序的管家。管家拥有较高的权限,可以访问和操作本地资源,使用原本在浏览器中不提供的高级API。同时管家也管理着渲染进程窗口的创建和销毁。所以,我们将这个管家称之为主进程。在使用Electron开发的程序中,会使用main.js作为程序的主入口,该文件内代码执行的内容,就是主进程中执行的内容。

2.2.1 主进程‌‌

‌‌主进程控制应用程序的生命周期。Electron 用来运行 package.json 的 main 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。它内置了完整的Node.js API,主要用于打开对话框以及创建渲染进程。此外,主进程还负责处理与其他操作系统交互、启动和退出应用程序。

主进程就像是应用程序的管家,负责管理整个应用程序的生命周期以及所有渲染进程的创建。

按照惯例,主进程位于名为main.js的文件中,你可以通过在package.json文件中修改配置属性来更改主进程文件。

请注意,Electron有且只有一个主进程。且主进程销毁时,所有渲染进程也将一并销毁。在chrome浏览器的默认策略下,每一个tab都是独立的进程,Electron也正是利用了这一策略。

2.2.2 渲染进程

渲染进程是应用程序中的浏览器窗口。与主进程不同,Electron可以有许多渲染进程,且每个进程都是独立的。由于 Electron 使用了 Chromium 来展示web 页面,所以 Chromium 的多进程架构也被使用到。 每个Electron中的 web 页面运行在它自己的渲染进程中。

正是因为每个渲染进程都是独立的,因此一个崩溃不会影响另外一个,这些要归功于Chromium的多进程架构。

2.2.3 如何保持进程通信?

即便Electron中的所有进程同时存在并保持独立运行,但他们仍然需要以某种方式进行沟通,尤其是在他们负责不同任务的时候。

为了保持进程通信,Electron有一个进程间通信系统(IPC也就是内部进程通信)。可以使用IPC在主进程和渲染进程之间传递信息。

// 在主进程中
global.sharedObject = {
someProperty: 'default value'
}Copy
// 在第一个页面中
require('electron').remote.getGlobal('sharedObject').someProperty= 'new value'Copy
// 在第二个页面中
console.log(require('electron').remote.getGlobal('sharedObject').someProperty)

Electron 进程通信的实现方式:

  • 主进程使用 BrowserWindow 实例创建页面。每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。
  • 主进程管理所有的web页面和它们对应的渲染进程。 每个渲染进程都是独立的,它只关心它所运行的 web页面。
  • 在页面中调用与 GUI 相关的原生 API 是不被允许的,因为在 web 页面里操作原生的GUI 资源是非常危险的,而且容易造成资源泄露。 如果你想在 web 页面里使

用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。

题外话:在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API。 其中比较好的方案是用 Storage API, localStorage,sessionStorage 或者 IndexedDB。

2.2.4 如何构建 Electron系统架构?

为了降低构建整个 Chromium 带来的复杂度,Electron通过libchromiumcontent 来访问 Chromium 的Content API。libchromiumcontent 是一个独立的、引入了 Chromium Content 模块及其所有依赖的共享库。用户不需要一个强劲的机器来构建Electron。

Electron只用了Chromium的渲染库而不是其全部组件。这使得升Chromium更加容易,但也意味着Electron缺少了Google Chrome里的一些浏览器相关的特性。

2.2.5 打包

原来打包步骤略微繁琐,如今由于社区发展,产生了很多优秀的打包工具,让我们可以不用关注很多细节,(比如asar)

// 在主进程中
global.sharedObject = {
someProperty: 'default value'
}Copy
// 在第一个页面中
require('electron').remote.getGlobal('sharedObject').someProperty= 'new value'Copy
// 在第二个页面中
console.log(require('electron').remote.getGlobal('sharedObject').someProperty)
main 端
ipcMain.on('readFile', (event, { filePath })=> {
content content = fs.readFileSync(filePath,'utf-8');
event.sender.send('readFileSuccess', { content});
});
renderer 端
ipcRenderer.on('readFileSuccess', (event, {content }) => {
console.log(`content: ${content}`);
});
ipcRender.send('readFile', {
filePath: '/path/to/file',
});

我们仅需做的 :将app 的目录结构整理好,提供对应的资源,如icon等,然后使用工具制作镜像即可将资源打包成为各个平台下的APP应用。

  • 打包工具的选择‌‌

    ‌‌通常情况下,我们选择Electron-builder (跨平台支持性较好,上手成本低)。

    Electron-builder 提供了自动下载、自动构建、自动打包、自动升级等能力,是 Electron 生态中的基础支持工具,大部分流行的 Electron 应用都使用它进行构建和分发。[1]

  • Electron打包配置

    "build": {
    "appId": "your.id", // appid
    "productName": "程序名称",// 程序名称
    "files": [ // 打包需要的不过滤的文件
    "build/**/*",
    "main.js",
    "node_modules/**/*"
    ],
    "directories": {
    "output": "./dist-out", // 打包输出的目录
    "app": "./", // package所在路径
    "buildResources": "assets"
    },
    "nsis": {
    "oneClick": false, // 是否需要点击安装,自动更新需要关掉
    "allowToChangeInstallationDirectory":true, //是否能够选择安装路径
    "perMachine": true // 是否需要辅助安装页面
    },
    "win": {
    "target": [
    {
    "target": "nsis", // 输出目录的方式
    "arch": [ // 输出的配置ia32或者x64/x86
    "x64"
    }
    ],
    "publish": [ // 自动更新的配置
    {
    "provider": "generic", // 自己配置更新的服务器要选generic
    "url":"http://127.0.0.1:8080/updata/" //更新配置的路径
    }
    }
    }
    

三、Electron的配置流程[2]

[如何利用 Electron 开发一个桌面 APP](如何利用 Electron 开发一个桌面 APP)[4]

Electron 应用实战 (架构篇)[5]

这里我们只简单的介绍下如何使用Electron写一个经典的Hello World。

  • 首先,新建一个目录,初始化npm

    mkdir helloword
    npm init
    
  • 修改package.json文件,增加npm run start命令

    {
      "name": "electron demo",
      "version": "1.0.0",
      "description": "",
      "main": "main.js",   //修改为main.js
      "scripts": {
        "start": "electron ."  //增加start命令
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "electron": "3.0.10"
      }
    }
    
  • 通过npm安装Electron

    npm i electron --save-dev
    
  • 在根目录创建main.js和index.html

    • main.js

      ```
      const { app, BrowserWindow } = require('electron')
        
      function createWindow () {   
        // 创建浏览器窗口
        win = new BrowserWindow({ width: 800, height: 600 })
        
        // 然后加载应用的 index.html。
        win.loadFile('index.html')
      }
        
      app.on('ready', createWindow)
      ```
      
      • index.html

        <!DOCTYPE html>
        <html>
          <head>
            <meta charset="UTF-8">
            <title>Hello World!</title>
          </head>
          <body>
            <h1>Hello World!</h1>
          </body>
        </html>
        

到这里,我们所有的准备工作都完成了,接下来就是运行它!

npm run start

看看效果

四、Electron的应用场景[1]

4.1 软件开发领域

在软件开发领域,最为开发人员所熟知的无过于 Visual Studio Code 了。Visual Studio Code 依靠丰富的功能、极速的响应、极佳的用户体验赢得了广大开发人员的青睐。作为一个新兴的 IDE 工具,其在最近一期的 IDE 排行榜单中排名第七,用户量持续迅猛增长。

另外,MongoDB 桌面版管理工具 Compass 也是基于 Electron 开发的。

4.2 社交通信领域

社交通信领域风靡全球的 Skype 桌面版和 WhatsApp 桌面版、高效办公领域的 Slack 和飞书、视听领域的 Nuclear(一款很有趣的音乐播放器)和 WebTorrent Desktop(以P2P协议播放音视频的应用)、金融交易领域的 OpenFin、早期的以太坊客户端 Mist 和 Brave 浏览器(由前 Mozilla CEO 和 JavaScript 之父 Brendan Eich 创建)等,都是基于 Electron 打造的。

4.3 Web 界面测试领域

Electron 还被用于 Web 界面测试。自 PhantomJS 宣布停止更新后,Electron 成了有力的替代者。

测试工程师可以通过编写自动化测试脚本,轻松地控制 Electron 访问网页元素、提交用户输入、验证界面表现、跟踪执行效率等。另外,知名的 HTTP 网络测试工具 Postman 也是基于 Electron 开发的。

4.4 Electron 是极客喜爱的工具

由于 Electron 有自定义代理、截获网络请求、注入脚本到目标网站的能力,它也成了众多极客的趁手工具,比如有开发者开发过一个音乐聚合软件,把 QQ 音乐、网易云音乐、虾米音乐聚合在一个软件里播放。

如果你基于 Electron 开发了软件,也完全可以自由地把你的产品分享到 Electron 的官网(https://github.com/electron/apps/blob/master/contributing.md#adding-your-app)。

五、Electron对比其他开发框架的优势

‌‌Electron的出现将蚕食很大一部分桌面客户端领域的市场份额,鉴于它的跨平台特性,在不同系统之间仅需少量的优化工作。可想而知,这个成本到底有多低。在开发的体验上,Electron是基于"Chromium"和"Node.js"的,所以几乎所有的Node.js模块都可以在Electron上运行,并很容易使用“npm”搭积木的方式快速交付一个产品。[3]

Electron 基于 Web 技术开发桌面应用。Web 技术是现如今软件开发领域应用最广泛的技术之一,入门门槛非常低,周边生态繁荣而且历史悠久。

5.1 Electron 开发效率高

相较于基于 C++ 库开发桌面软件来说,基于 Electron 开发更容易上手且开发效率更高。由于 JavaScript 语言是一门解释执行的语言,所以 C++ 语言固有的各种问题都不再是问题,比如:

  • C++ 没有垃圾回收机制,开发人员要小心翼翼地控制内存,以免造成内存泄漏;
  • C++ 语言特性繁多且复杂,学习难度曲线陡峭,需要针对不同平台进行编译,应用分发困难。

使用 Electron 开发桌面应用就不用担心这些问题。

5.2 Electron 执行效率高

在执行效率上,如果前端代码写得足够优秀,Electron 应用完全可以做出与 C++ 应用相媲美的用户体验,Visual Studio Code 就是先例。

另外,Node.js 本身也可以很方便地调用 C++ 扩展,Electron 应用内又包含 Node.js 环境,对于一些音视频编解码或图形图像处理需求,可以使用 Node.js 的 C++ 扩展来完成。

5.3 Electron 立足于 JavaScript 生态

随着 Web 应用大行其道,Web 前端开发领域的技术生态足够繁荣。Electron 可以使用几乎所有的 Web 前端生态领域及 Node.js 生态领域的组件和技术方案。截至本文发布时,发布到 npmjs.com 平台上的模块已经超过 90 万个,覆盖领域广,优秀模块繁多且使用非常简单方便。

5.4 无需考虑兼容性问题

在完成 Web 前端开发工作时,开发者需要考虑很多浏览器兼容的问题,比如:用户是否使用了低版本的 IE 浏览器,是否可以在样式表内使用 Flexbox(弹性盒模型)等。这些问题最终会导致前端开发者束手束脚,写出一些丑陋的兼容代码以保证自己的应用能在所有终端表现正常。

但由于 Electron 内置了 Chromium 浏览器,该浏览器对标准支持非常好,甚至支持一些尚未通过的标准,所以基于 Electron 开发应用不会遇到兼容问题。开发者的自由度得到了最大化保护,你可以在 Electron 中使用几乎所有 HTML5、CSS3、ES6 标准中定义的 API。

5.5 Electron 可以使用操作系统接口

另外,Web 前端受限访问的文件系统、系统托盘、系统通知等,在 Electron 技术体系下均有 API 供开发者自由使用。

六、Electron对比其他开发框架的不足

桌面端框架Electron使用问题整理和总结[6]

基于 Electron 开发桌面 GUI 应用并不是完美的方案,它也有它的不足,综合来说有以下几点。

6.1 打包后的应用体积巨大

一个功能不算多的桌面应用,通过 electron-builder 压缩打包后至少也要 40MB。如果开发者不做额外的 Hack 工作的话,用户每次升级应用程序,还要再下载一次同样体积的安装包,这对于应用分发来说是一个不小的负担。但随着网络环境越来越好,用户磁盘的容积越来越大,此问题给用户带来的损失会慢慢被削弱。

6.2 开发复杂度较大,进阶曲线较陡

跨进程通信是基于 Electron 开发应用必须要了解的知识点,虽然 Electron 为渲染进程提供了 remote 模块来方便开发人员实现跨进程通信,但这也带来了很多问题,比如某个回调函数为什么没起作用、主进程为什么报了一连串的错误等,这往往给已经入门但需要进阶的开发者带来困惑。

6.3 版本发布过快

为了跟上 Chromium 的版本发布节奏,Electron 也有非常频繁的版本发布机制,每次 Chromium 改动,都可能导致 Electron 出现很多新问题,甚至稳定版本都有很多未解决的问题。幸好 Electron 的关键核心功能一直以来都是稳定的。

6.4 安全性问题

Electron 把一些有安全隐患的模块和 API 都设置为默认不可用的状态,但这些模块和 API 都是非常常用的,因此有时开发者不得不打开这些开关。但是,一旦处理不当,就可能导致开发的应用存在安全隐患,给开发者乃至终端用户带来伤害。

安全问题有很多值得关注的技术细节,以至于 Electron 官方文档中专门开辟出来一个章节号召程序员重视安全问题。但我认为,很多时候安全和自由是相悖的,在不损失自由的前提下提升安全指标的工作是值得肯定的,如果哪天 Electron 以安全为由停用脚本注入的技术,相信很多开发者都会反对。

6.5 资源消耗较大

Electron 底层基于的 Chromium 浏览器一直以来都因资源占用较多被人诟病,目前来看这个问题还没有很好的解决办法,只能依赖 Chromium 团队的优化工作。

6.6 操作系统版本限制

除了以上这些问题外,Electron 还不支持老版本的 Windows 操作系统,比如 Windows XP。在中国还有一些用户是使用 Windows XP 的,开发者如果需要面向这些用户,应该考虑使用其他技术方案。

参考资料

[1]:Electron | 是什么?

[2]:Electron系列文章 | 什么是Electron?

[3]:初探Electron | 从入门到实践

[4]:如何利用 Electron | 开发一个桌面 APP

[5]:Electron | 应用实战 (架构篇)

[6]:桌面端框架Electron | 使用问题整理和总结

[7]:嵌入式浏览器安全杂谈 | electron框架

[8]:Electron | 架构揭秘

© 版权声明
THE END
喜欢就支持以下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容