「如何实现流动式软件发布」线上课堂开课啦,快来报名参与课堂抽奖吧~ 了解详情
写点什么

创建优秀 Electron APP 的秘诀

2019 年 7 月 02 日

创建优秀Electron APP的秘诀

如何用 Electron 创建 app,有些人认为这些 app 会吃内存,使启动变慢,响应变慢。但事实是否如此呢?知名开发人员和设计师 JAMES LONG 将在本文中分享他的秘诀。


有些人真的很讨厌 Electron app。用 app 完全复制 Chrome 浏览器上所有东西的想法听起来颇为荒谬。当你看着自己电脑上的 app 时,这种感觉进一步被确认了。这些 app 会吃内存,使启动变慢,响应变慢。在 web 端创建优秀的 app 本身就有难度,为什么我们还要将 web 加入桌面,制造出更多的问题?


我不会花时间为 Electron 辩护,但 Electron 之所以能成功,很明显这背后有正当的动机。但是,我们不希望让 Electron 太膨胀。那么,我们能否鱼和熊掌兼得呢?


Electron 的一些问题(如文件大、启动时间长)是其架构中固有的,需要在更低的级别上予以解决。更严重的问题(如吃内存和速度慢)可以在用户层面予以解决,但是这并不容易。如果我告诉你有一个秘诀可以自动地最大化地减少这些问题,你会作何反应?


这个秘诀就是在本地的后台进程中完成大部分的工作。你越不依赖云,你的后台进程就会越强大,你就越能够收获以下这些显而易见的好处:


  • 即时加载数据。你从不需要等待数据通过网络加载,因为数据是直接从本地的数据源加载的。这一点会使速度大幅提升。

  • 极少需要缓存。由于所有数据都可以即时获取,客户端不需要太关心缓存。通常,web app 需要创建许多本地状态,才能获得较好的性能,而这正是内存膨胀的一个原因。


因为本帖子不打算涉及,在这里我没有说其它好处,比如 app 可以在离线状态下工作等等。


下面就是我如何创建个人财务管理器Actual的过程。它是 100%本地的,但它也提供了在不同设备间同步这一可选功能。对于一个重数据的 app 来说,Actual 的结果好坏不言而喻,见下图:



当 app 休息时,总共占用了 239.1MB 内存(根据页面不同,该数字还会上升,但 239.1MB 是一个基准)。虽然该数字不算理想,但是也不差。因为相比于目前占用我电脑 1371MB 内存的 Slack 来说,这一结果要好得多。虽然 Slack 表现差,但 Electron 却因其特有的问题遭受了太多的抨击。其它 app 如 Notion 和 Airtable 的数字大约为 400-600MB,所以说 Actual 仍然打败了它们。


而这还只是我未进行任何优化前的情况。我打算用 Rust 重写其中一个关键且内存密集型的部件。若完成,预计将大幅降低 Actual 的内存用量。


后台服务器可以只把需要的数据加载到内存中,来优化其内存用量。最好的办法是使用 SQLite 之类的东西,因为SQLite已经针对这一任务做过高度优化(所以,用 SQLite 吧)。将一些东西移到后台进程中将会释放 UI,加快其响应速度。


另外,还有一个好处是,在 Electron 中使用后台服务器还能提供极佳的开发者体验。若不信,请看看随后的章节,了解一下你可以做哪些难以置信的事情。


即使你的 app 严重依赖于 web,如果你需要访问节点 API,你也可能需要后台进程。后台进程是我所知唯一能够安全访问这些 API 的地方。此项目将帮助你学习如何一步步将它构建起来。


Electron 与服务器示例介绍

为了鼓励大家打造出真正本地的 Electron app,我创建了一个electron服务器示例来展示所有过程。这个项目也是我最开始使用 Electron 时希望存在的项目。


所有的技术细节都保存在 README 文件中。下面是该示例高级别的概述:


  • 它创建了一个常见的节点进程在后台运行服务器;

  • 创建了一个使用node-ipc的 IPC 通道,直接与后端和 UI 通信;

  • 在开发模式下,它可以在另一个调试窗口内运行服务器,而不是将服务器视为一个后台进程。


等等,最后一点怎么回事?在开发模式下,它在一个窗口内运行服务器?



没错!在我让后台进程运行后,我发现所有的 Chrome 开发者工具都在那里,并且我可以创建一个带有节点集成的窗口。也就是说,我可以很容易地在一个窗口内加载节点进程,而不是在后台中,与此同时,我可以访问所有的 Chrome 调试开发工具。


看看你现在可以做的事情,很酷,是吧!


使用酷炫的控制台

我在 server-ipc.js 中添加了日志记录,以记录所有的请求和回复。而且,我可以通过酷炫的控制台检查这些日志:



步骤调试

你可以自然地使用步骤调试工具。它并非独创,但拥有它总是更好的选择,因为当你有需要时,你不再需要设置节点检查工具。



剖析!

或许我最喜欢的功能莫过于恒星性能工具,它们总是一点即用。你可以用它们来轻松地剖析任何后端部件。



通过记录和重新加载窗口,你甚至可以剖析后台进程的启动时间(这或许是启动耗时最长的环节)!而重新加载会重启服务器。于是,我们来到了下一步。


用 Cmd+R 重启服务器

我最喜欢的另一点是:由于服务器运行在窗口中,重新加载窗口会重启服务器!按 Cmd+R (如果你在使用 Windows 的话,则按 Ctrl+R)会重启服务器,你不再需要重启前台进程。


也就是说,你可以对服务器进行变更,然后按下 Cmd+R,变更就更新了,不需要做其它事!前端会保持其当前的状态,而你可以在最新的服务器上继续工作。在某种程度上,就像你给服务器打热补丁一样。


如下图所示,我变更了一些节点,按下 Cmd+R,然后刷新服务器,最后继续使用客户端。



在线检查和热修补服务器

通常我只需要添加控制台日志或作一些微调,然后重启服务器。但是有时候,如果你正在调试一些十分棘手的东西,那么探究一下当前服务器状态以查明究竟发生了什么对你十分有帮助。甚至,我们可以在服务器运行的时候,改变一些东西,看看究竟会产生什么影响。


在控制台中,你可以进行节点的 require!也就是说,你可以 require 任何服务器模块并侵入它们。例如,为了获取 server-handlers.js 模块,你可以在模块中让 handlers = require(’./server-handlers’)。


让我们添加一些服务器状态,即所有传输给 make-factorial 的数字记录(真实的 app 的服务器状态比这要复杂得多):


handlers._history = []handlers['make-factorial'] = async ({ num }) => {  handlers._history.push(num)}
复制代码


现在我们便可以通过要求该模块和查看 handlers._history 在控制台中进行检查了。我们甚至可以在 run-time 中完全替换 make-factorial 的执行。



结论

浏览electron服务器示例,阅读执行详情和所有后端服务器的代码。


如果你会使用 Visual Studio Code,你可能已经习惯了开发者工具和后端节点服务器之间良好的集成。虽然你可以自己单独运行服务器,然后让 Electron 将该服务器连接到 Visual Studio Code 拥有的进程,但是我发现,重新使用 Electron 现成的开发者工具要简单得多。这也意味着你可以使用任何你喜欢的编辑器,而且你可以访问所有的工具,包括剖析器。


过去几年,我经常使用上述技巧来开发 Actual,而且我对此非常高兴,因为这可能是我所拥有的最好的节点开发经历。


同样关键的是,我们得开始开发真正的本地 app 了。所有的技术都在这了,我们只需要关注它们。本文重点关注了使用后端服务器和开发 100%本地的 app 的技术优势,而没有谈到其它优势,譬如可用性(无论有无网络连接)。未来,我将撰写更多有关内容以及介绍如何在 Actual 中进行同步。


作者介绍:


JAMES LONG 是一名开发人员和设计师,拥有超过 10 年的构建大型 app 的经验。他创造了 JavaScript 代码格式化标准 Prettier,并领导了一项将 Firefox 开发者工具移植到 Mozilla React 的项目。他是 Actual 的创始人,并且通过自己的博客拓展编程的新理念。他重点关注如何为用户解决真正的问题,提升用户体验。


原文链接


THE SECRET OF GOOD ELECTRON APPS


2019 年 7 月 02 日 16:185595
用户头像

发布了 34 篇内容, 共 16.5 次阅读, 收获喜欢 45 次。

关注

评论

发布
暂无评论
发现更多内容

Ansible Playbook - 03

耳东

ansible 7月日更 ansible Playbook

并发操作详解:Goroutines 和 Channels 的声明与使用

微客鸟窝

golang调度 go并发

自建开发工具系列-Webkit内存动量监控UI(七)

Tim

Script tsconfig

如何在 Discourse 中配置使用 GitHub 登录和创建用户

HoneyMoose

基础SQL的实现

卢卡多多

7月日更

Linux之chgrp命令

入门小站

Linux

【Flutter 专题】85 Flutter Attach 调试 Flutter Code

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

前端通讯协议大比拼:WebSockets和HTTP

devpoint

HTTP websocket HTTP2.0 7月日更

“此苹果非彼苹果”看意图识别的那些事儿

百度大脑

人工智能 飞桨 数据抽取

模块二作业

江南巴飞特

Vue进阶(幺陆贰):vue render函数介绍

No Silver Bullet

Vue 7月日更 render

MapReduce的参数优化

大数据技术指南

7月日更

网络攻防学习笔记 Day75

穿过生命散发芬芳

网络攻防 7月日更

你也许连删库跑路都不会

喵叔

7月日更

在线SVG在线编辑器

入门小站

Linux

推荐大家一个阅读全球计算机论文的好RP

奔着腾讯去

浪潮位居全球区块链企业前十、中国前三

浪潮云

ClickHouse大数据领域企业级应用实践和探索总结

王知无

数据中台发展史

escray

极客时间 学习笔记 7月日更 数据中台实战课

B站崩了,拉垮了豆瓣?程序员不要怕,Alibaba架构师教你如何“预防”

Java架构师迁哥

手写冒泡排序和选择排序算法

实力程序员

Vue进阶(幺肆拐):利用Vue中keep-alive快速实现页面缓存

No Silver Bullet

Vue 7月日更 keep-alive

傻眼了,我粗略造了一个命令执行的绕过方法居然被同事嫖走了

网络安全学海

黑客 网络安全 信息安全 渗透测试 漏洞分析

Kubernetes-技术专题-Spring Boot 2.0和 Docker 的微服务快速指南

李浩宇/Alex

容器 k8s 7月日更

难受的一天

IT蜗壳-Tango

7月日更

到底是先更新数据库还是先更新缓存?

冰河

数据库 缓存 系统架构 分布式系统 缓存一致性

Rust从0到1-并发-线程间消息传递

rust 并发 channel 消息传递 Message Passing

【大数据面试之对线面试官】MapReduce/HDFS/YARN面试题70连击

王知无

Redis - Cluster - gossip&故障转移

旺仔大菜包

redis cluster

Apache Spark结构化API(三)

数据与智能

spark API RDD

【LeetCode】在排序数组中查找数字 Java题解

HQ数字卡

算法 LeetCode 7月日更

创建优秀Electron APP的秘诀-InfoQ