不久前,我开始从事一个名为Taggr的附带项目,这是一个完全离线的交互式照片探索应用程序。开发Taggr要求我从应用程序复杂性的最低级别开始,尝试多种架构方法并探索每种局限性。
在本文中,我们将讨论使用electron构建桌面应用程序的不同构建方法之间的权衡。我们将分析每个不同方法的缺点,并介绍旨在应对它们的架构。
本文中介绍的蓝图是持续努力的结果,以找到一种方法,使我(一个独立开发人员)通过利用标准网络工具来管理应用程序的复杂性并满足性能要求。让我们开始吧!
在过去的几年中,在浏览器领域内的JavaScript使用情况大大增加,在很大程度上是借助库和框架(例如React,Vue和Angular)的帮助。同样,JavaScript已经不仅仅局限于在浏览器中使用,而是可以在其他地方使用,比如Node.js、Deno和ReactNative。
Electron.js就是这些框架之一。自2013年发行以来,Electron已成长为构建跨平台桌面应用程序最常用的框架之一。VSCode,Slack,Twitch和许多其他流行的桌面应用程序是使用Electron构建的。
Electron将Chromium和Node.js嵌入其二进制中,使Web开发人员能够在不编写原生桌面应用代码的情况下编写桌面应用程序。Electron实现了一个与Chromium浏览器类似的由主进程和渲染进程组成的多进程模型。
每个应用程序的窗口都是一个渲染进程。每个窗口之间是相互隔离的执行上下文,主进程程负责应用程序生命周期管理,窗口管理或渲染进程管理,以及一些nativeAPI(例如系统菜单,通知和托盘图标)等。
每个应用程序由一个主进程和一个可变数量的渲染进程组成。渲染进程可用于JavaScript代码执行,也可以在没有UI的情况下存在。
注意:Electron不是构建跨平台桌面应用的唯一选择。其他替代方案也提供了更少的资源消耗和更小的可执行文件,但没有活跃的共享社区,学习资源或者得到像Electron一样的广泛传播和使用。
如果您还不熟悉Electron,它很容易上手,因为Node.js和JavaScript的知识是可以互通的。
Electron抽象出原生应用层和熟悉的js语言,减少了推广和开发成本。从本质上讲,Electron在桌面应用程序开发中所做的工作类似于ReactNative对移动开发的开发。
Electron还可以管理构建和部署,以及应用程序更新,从而易于将跨平台应用程序保持同步的更新。您可以通过运行时加载远程资源来实现自动更新。
但是,Electron带来了一些便利和好处,同时在权衡利弊中,也带来了一些不可避免的问题。Electron开发框架默认包含了Chromium和Node.js环境。导致Electron应用比使用本地开发会消耗更多的资源。因此,一些人对Electron的性能和资源消耗表示担忧。
此外,由于基础体系结构,复杂的Electron应用程序会对应用程序的性能和开发人员来带一些挑战。我们通过三个不同的应用程序示例来进行深入分析。
让我们研究具有不同复杂性的三个应用程序示例的高级结构设计。请注意,我们的目的并不是要详尽,而是旨在分析您可以使用Electron构建的什么样(能力边界)的应用。
让我们从一个低复杂的应用程序开始。就我们的示例而言,我们将将网页包装为桌面应用程序。示例可能包括即时消息传递应用程序,数据分析仪表板和在线流应用程序。
许多企业提供基于成熟的Web的应用程序的桌面版本,使我们的使用情况成为常见的用例。我们将使用Electron运行在chrome上的应用程序,消除不必要的差异,并提供统一的UI,而不是不同的浏览器有不同表现。
像Spotify这样的音乐流应用程序,它是使用本地缓存提供脱机流支持的,是一个典型具有中等复杂性的应用程序的示例。桌面应用程序可以使用Electron来构建本地缓存层。
与低复杂性应用相似,中等复杂的应用程序也可以补充网络应用程序。主要区别是提供离线支持的能力。因此,这些应用在概念上与脱机支持的渐进式Web应用程序(PWA)相似。
对于最高级别的复杂性,让我们看一下像Sharp这样的批处理图像处理应用程序。该应用程序必须能够处理数千个图像并完全离线工作。
离线应用程序与前两个示例明显不同。具体而言,典型的后端工作负载(例如图像处理)将通过创建离线应用程序在Electron中执行。
请注意,绝不能在主进程中运行CPU密集型操作。这样做可能会阻塞主进程,从而导致您的应用程序卡住或者崩溃。
此外,将业务逻辑和通信层与ElectronAPI耦合限制了重复使用Web开发工具的原则。主进程和渲染器进程之间的通信使用IPC,在两个渲染过程之间进行通信时,需要通过主进程进行信息的来回传递。
如果您的应用程序属于低或中复杂性类别,恭喜!离线应用程序中出现的许多坑都不会遇到。但是,如果您的应用程序需求落在高复杂性范围内,那就难说了!
让我们详细介绍每个模块!
注意:部分技术栈纯粹是依据个人喜好而选择的,并且可以使用其它技术替换。例如,您可以将typescript交、替换为JavaScript,React替换VUE,REDUX替换MOBX或使用其它的NPM软件包管理器替换yarn,而不是完全遵照上述示例。只要尊重上述思路,您就可以自由选择技术栈。
使用yarnworkspace来实现CodeShing,这是将模块作为NPM软件包发布,更新和版本化的简单替代方法。
前端模块负责UI的所有内容。它包含我们应用程序的组件和动画,但不包含业务逻辑。在生产环境中,Electron从生成的静态文件中使用它。
后端模块包含后端代码库和电子设置代码。业务逻辑和长期运行的操作(例如图像处理)将在单独的node.js流程中运行,以使UI不会遭受降级性能。
前端和后端使用node-ipc传递的跨进程消息进行通信。消息传递允许异步和基于事件的通信。
异步通信最适合短时任务。前端可以在后端成功处理消息后立即获取结果。
Electron是使用不同的Web技术构建跨平台桌面应用程序的不错选择。尽管Electron更适合在低复杂性应用中使用,但是随着复杂性的增加,性能和开发人员的经验和能力水平将显得更为重要。
本文所提出的架构旨在为高复杂性应用程序提供合理的理论基础。当然,它可能需要根据具体情况进行扩展,而且它为不同类型应用程序提供了很好的理论支持。