跳到主要内容

协议处理程序漏洞修复

·2 分钟阅读

发现了一个影响使用自定义协议处理程序的 Electron 应用的远程代码执行漏洞。此漏洞已分配 CVE 标识符 CVE-2018-1000006


受影响的平台

设计在 Windows 上运行的 Electron 应用,如果它们将自己注册为协议(例如 myapp://)的默认处理程序,则会受到攻击。

无论如何注册协议,例如使用本机代码、Windows 注册表或 Electron 的 app.setAsDefaultProtocolClient API,此类应用都可能受到影响。

macOS 和 Linux 不受此问题影响

缓解措施

我们发布了新版本的 Electron,其中包含对此漏洞的修复:1.8.2-beta.51.7.121.6.17。我们敦促所有 Electron 开发人员立即将其应用更新到最新的稳定版本。

如果由于某种原因您无法升级 Electron 版本,则可以在调用 app.setAsDefaultProtocolClient 时将 -- 作为最后一个参数附加,这会阻止 Chromium 解析其他选项。双破折号 -- 表示命令选项的结尾,之后只接受位置参数。

app.setAsDefaultProtocolClient(protocol, process.execPath, [
'--your-switches-here',
'--',
]);

有关更多详细信息,请参阅 app.setAsDefaultProtocolClient API。

要了解有关保持 Electron 应用安全的最佳实践的更多信息,请参阅我们的安全教程

如果您希望报告 Electron 中的漏洞,请发送电子邮件至 [email protected]

Electron 2.0 及更高版本 - 语义版本控制

·一分钟阅读

Electron 的新主要版本正在开发中,同时我们对版本控制策略进行了一些更改。从 2.0.0 版本开始,Electron 将严格遵守语义版本控制。


此更改意味着您会更频繁地看到主要版本号的升级,并且它通常是 Chromium 的主要更新。修补程序版本也会更加稳定,因为它们现在只会包含错误修复,而不会包含新功能。

主要版本递增

  • Chromium 版本更新
  • Node.js 主要版本更新
  • Electron 破坏性 API 更改

次要版本递增

  • Node.js 次要版本更新
  • Electron 非破坏性 API 更改

修补程序版本递增

  • Node.js 修补程序版本更新
  • 与修复相关的 Chromium 修补程序
  • Electron 错误修复

由于 Electron 的 semver 范围现在将更有意义,我们建议使用 npm 的默认 --save-dev 标志安装 Electron,该标志将在您的版本前缀 ^,使您能够安全地保持最新的次要版本和修补程序更新

npm install --save-dev electron

对于只对错误修复感兴趣的开发人员,您应该使用波浪号 semver 前缀,例如 ~2.0.0,这将永远不会引入新功能,只会引入修复以提高稳定性。

有关更多详细信息,请参阅 electronjs.org/docs/tutorial/electron-versioning

Electron 的新国际化网站

·6 分钟阅读

Electron 在 electronjs.org 有一个新网站!我们用 Node.js Web 服务器替换了我们的静态 Jekyll 站点,使我们能够灵活地对站点进行国际化,并为更多令人兴奋的新功能铺平道路。


🌍 翻译

我们已经开始对网站进行国际化,目标是让全球开发人员都能访问 Electron 应用开发。我们正在使用一个名为 Crowdin 的本地化平台,该平台与 GitHub 集成,当内容被翻译成不同的语言时,会自动打开和更新拉取请求。

Electron Nav in Simplified Chinese

尽管我们一直在默默地进行这项工作,但已有 75 多名 Electron 社区成员自发地发现了该项目,并加入了将网站国际化并将 Electron 的文档翻译成 20 多种语言的工作。我们每天都能看到来自世界各地人们的贡献,其中法语、越南语、印尼语和中文等语言的翻译走在前列。

要选择您的语言并查看翻译进度,请访问 electronjs.org/languages

Translations in progress on Crowdin

如果您是多语种并且有兴趣帮助翻译 Electron 的文档和网站,请访问 electron/electron-i18n 存储库,或直接在 Crowdin 上开始翻译,您可以使用您的 GitHub 帐户登录。

目前,Crowdin 上为 Electron 项目启用了 21 种语言。添加对更多语言的支持很容易,因此如果您有兴趣帮助翻译但没有看到您的语言列出,请告诉我们,我们将启用它。

原始翻译文档

如果您更喜欢阅读原始 markdown 文件中的文档,您现在可以使用任何语言执行此操作

git clone https://github.com/electron/electron-i18n
ls electron-i18n/content

应用页面

现在,任何 Electron 应用都可以轻松地在 Electron 网站上拥有自己的页面。例如,请查看 Etcher1ClipboardGraphQL Playground,这里展示的是日文版网站上的截图。

GraphQL Playground

市面上有一些非常出色的 Electron 应用,但它们并不总是容易被发现,而且并非每个开发者都有时间和资源来构建一个合适的网站来推广和发布他们的应用。

我们仅使用一个 PNG 图标文件和少量应用元数据,就能够收集到有关特定应用的许多信息。通过从 GitHub 收集的数据,应用页面现在可以显示截图、下载链接、版本、发行说明和 README,这些信息针对每个拥有公共仓库的应用。使用从每个应用的图标中提取的调色板,我们可以生成大胆且易于访问的颜色,使每个应用页面都具有一定的视觉区分度。

应用索引页面 现在还具有类别和关键字过滤器,可以查找诸如 GraphQL GUIp2p 工具等有趣的应用。

如果您有一个希望在网站上展示的 Electron 应用,请在 electron/electron-apps 仓库上打开一个拉取请求。

使用 Homebrew 一行安装

macOS 的 Homebrew 包管理器有一个名为 cask 的子命令,它可以让你使用终端中的一个命令轻松安装桌面应用程序,例如 brew cask install atom

我们已经开始收集流行的 Electron 应用的 Homebrew cask 名称,现在在每个有 cask 的应用页面上显示安装命令(针对 macOS 访客)。

Installation options tailored for your platform: macOS, Windows, Linux

要查看所有具有 Homebrew cask 名称的应用,请访问 electronjs.org/apps?q=homebrew。如果您知道其他我们尚未索引的具有 cask 的应用,请添加它们!

🌐 新域名

我们已将网站从 electron.atom.io 迁移到一个新域名:electronjs.org

Electron 项目诞生于 Atom 内部,Atom 是 GitHub 基于 Web 技术构建的开源文本编辑器。Electron 最初名为 atom-shell。Atom 是第一个使用它的应用,但很快人们就意识到这种神奇的 Chromium + Node 运行时可以用于各种不同的应用程序。当 Microsoft 和 Slack 等公司开始使用 atom-shell 时,很明显该项目需要一个新的名称。

因此,“Electron”诞生了。在 2016 年初,GitHub 组建了一个新团队,专门负责 Electron 的开发和维护,与 Atom 分开。自那时以来,Electron 已被数千名应用开发者采用,并且现在被许多大型公司所依赖,其中许多公司拥有自己的 Electron 团队。

支持 GitHub 的 Electron 项目(如 Atom 和 GitHub Desktop)仍然是我们团队的首要任务,但通过迁移到新域名,我们希望帮助明确 Atom 和 Electron 之间的技术区别。

🐢🚀 Node.js 无处不在

之前的 Electron 网站是使用流行的基于 Ruby 的静态网站生成器 Jekyll 构建的。Jekyll 是构建静态网站的好工具,但该网站已经开始超出它的能力。我们想要更多动态功能,例如适当的重定向和动态内容渲染,因此 Node.js 服务器是显而易见的选择。

Electron 生态系统包含许多使用不同编程语言编写组件的项目,从 Python 到 C++ 再到 Bash。但 JavaScript 是 Electron 的基础,也是我们社区中最常用的语言。

通过将网站从 Ruby 迁移到 Node.js,我们的目标是降低希望为网站做出贡献的人的入门门槛。

⚡️ 更容易参与开源

如果您的系统上安装了 Node.js(8 或更高版本)和 git,您可以轻松地在本地运行该网站。

git clone https://github.com/electron/electronjs.org
cd electronjs.org
npm install
npm run dev

新网站托管在 Heroku 上。我们使用部署管道和 Review Apps 功能,该功能会自动为每个拉取请求创建应用的运行副本。这使审阅者可以轻松查看拉取请求对网站实时副本的实际影响。

🙏 感谢贡献者

我们要特别感谢世界各地所有贡献自己的时间和精力来帮助改进 Electron 的人们。开源社区的热情在使 Electron 取得成功方面发挥了不可估量的作用。谢谢大家!

Thumbs up!

Chromium RCE 漏洞修复

·一分钟阅读

在 Google Chromium 中发现了一个远程代码执行漏洞,该漏洞会影响所有最新版本的 Electron。任何访问远程内容的 Electron 应用都容易受到此漏洞的攻击,无论是否启用 沙箱选项

我们发布了两个新版本的 Electron 1.7.81.6.14,这两个版本都包含此漏洞的修复程序。我们敦促所有 Electron 开发者立即将其应用更新到最新的稳定版本。

npm i electron@latest --save-dev

要了解有关保持 Electron 应用安全的最佳实践的更多信息,请参阅我们的安全教程

如果您希望报告 Electron 中的漏洞,请联系 [email protected]

宣布 Electron 中的 TypeScript 支持

·4 分钟阅读

electron npm 包现在包含一个 TypeScript 定义文件,该文件提供了整个 Electron API 的详细注释。这些注释可以改善您的 Electron 开发体验,即使您正在编写纯 JavaScript。只需 npm install electron 即可在您的项目中获取最新的 Electron 类型定义。


TypeScript 是一种由 Microsoft 创建的开源编程语言。它是 JavaScript 的超集,通过添加对静态类型的支持来扩展该语言。近年来,TypeScript 社区迅速发展,在最近的 Stack Overflow 开发者调查中,TypeScript 被评为最受欢迎的编程语言之一。TypeScript 被描述为“可扩展的 JavaScript”,GitHubSlackMicrosoft 的团队都在使用它来编写数百万用户使用的可扩展 Electron 应用程序。

TypeScript 支持 JavaScript 中许多较新的语言功能,如类、对象解构和 async/await,但其真正与众不同的特点是类型注释。声明程序期望的输入和输出数据类型可以通过帮助您在编译时查找错误来减少错误,并且这些注释还可以作为对程序工作方式的正式声明。

当库用纯 JavaScript 编写时,类型通常在编写文档时被模糊地定义为事后才考虑的问题。函数通常可以接受比文档中记录的更多类型,或者函数可以具有未记录的不可见约束,这可能会导致运行时错误。

TypeScript 通过定义文件解决了这个问题。TypeScript 定义文件描述了库的所有函数及其预期的输入和输出类型。当库作者将 TypeScript 定义文件与他们发布的库捆绑在一起时,该库的消费者可以直接在他们的编辑器中浏览其 API 并立即开始使用它,通常无需查阅库的文档。

许多流行的项目(如 AngularVue.jsnode-github (现在还有 Electron!)都会编译他们自己的定义文件并将其与他们发布的 npm 包捆绑在一起。对于那些不捆绑他们自己的定义文件的项目,还有 DefinitelyTyped,这是一个社区维护的定义文件的第三方生态系统。

安装

从 1.6.10 版本开始,每个 Electron 版本都包含自己的 TypeScript 定义文件。当您从 npm 安装 electron 包时,electron.d.ts 文件会自动与安装的包捆绑在一起。

安装 Electron 的 最安全的方法 是使用确切的版本号。

npm install electron --save-dev --save-exact

或者,如果您使用的是 yarn

yarn add electron --dev --exact

如果您已经在使用第三方定义(如 @types/electron@types/node),您应该将它们从您的 Electron 项目中删除,以防止任何冲突。

定义文件源自我们的 结构化 API 文档,因此它将始终与 Electron 的 API 文档保持一致。只需安装 electron,您将始终获得与您正在使用的 Electron 版本保持同步的 TypeScript 定义。

用法

有关如何安装和使用 Electron 的新 TypeScript 注释的摘要,请观看此简短的演示截屏视频。

如果您正在使用 Visual Studio Code,则已内置了 TypeScript 支持。还有用于 AtomSublimevim其他编辑器的社区维护插件。

一旦您的编辑器配置了 TypeScript,您将开始看到更多上下文感知的行为,例如自动完成建议、内联方法引用、参数检查等。

Method autocompletion

Method reference

Argument checking

TypeScript 入门

如果您是 TypeScript 的新手并想了解更多信息,Microsoft 的这段入门视频提供了一个很好的概述,介绍了该语言的创建原因、工作原理、使用方法以及发展方向。

在 TypeScript 官方网站上,还有一个手册和一个操场

由于 TypeScript 是 JavaScript 的超集,您现有的 JavaScript 代码已经是有效的 TypeScript 代码。这意味着您可以逐步将现有的 JavaScript 项目过渡到 TypeScript,并根据需要添加新的语言特性。

感谢

如果没有 Electron 开源维护者社区的帮助,这个项目是不可能完成的。感谢 Samuel AttardFelix RiesebergBirunthan MohanathasMilan BurdaBrendan Forster 以及许多其他人的错误修复、文档改进和技术指导。

支持

如果您在使用 Electron 的新 TypeScript 定义文件时遇到任何问题,请在 electron-typescript-definitions 存储库上提交问题。

祝您 TypeScript 编程愉快!

本周项目:Jasper

·5 分钟阅读

本周,我们采访了 Jasper 的创建者,Jasper 是一款基于 Electron 的工具,用于管理 GitHub 通知。


你好!你是谁?

我是 Ryo Maruyama,一名在日本的软件开发人员。我正在开发 JasperESDoc

什么是 Jasper?

Jasper 是一款灵活而强大的 GitHub 问题阅读器。它支持 github.com 和 GitHub Enterprise 上的问题和拉取请求。

Jasper App Screenshot

你为什么要做它?

当人们在工作或 OSS 活动中使用 GitHub 时,他们每天都会收到大量的通知。作为订阅通知的一种方式,GitHub 提供了电子邮件和Web 通知。我使用了这些几年,但我遇到了以下问题

  • 很容易忽略那些我被提及、我评论或我正在关注的问题。
  • 我把一些问题放在脑海里,打算稍后查看,但我有时会忘记它们。
  • 为了不忘记问题,我在浏览器中打开了很多标签页。
  • 很难检查所有与我相关的问题。
  • 很难掌握我团队的所有活动。

我花费了大量时间和精力来防止这些问题,所以我决定为 GitHub 创建一个问题阅读器,以高效地解决这些问题,并开始开发 Jasper。

谁在使用 Jasper?

Jasper 被许多使用 GitHub 的公司的开发人员、设计师和经理使用。当然,一些 OSS 开发人员也在使用它。甚至 GitHub 的一些人也在使用它!

Jasper 是如何工作的?

配置 Jasper 后,会出现以下屏幕。从左到右,您可以看到“流列表”、“问题列表”和“问题正文”。

Jasper Start Screen

这个“流”是 Jasper 的核心功能。例如,如果您想查看“在 electron/electron 存储库中分配给 @zeke 的问题”,您需要创建以下流

repo:electron/electron assignee:zeke is:issue

Jasper Start Screen 2

创建流并等待几秒钟后,您可以看到符合条件的问题。

Jasper Start Screen 3

我们可以用流做什么?

我将介绍流可以使用哪些条件。

用户和团队

问题
mentions:cat mentions:dog提及用户 catdog 的问题
author:cat author:dog由用户 catdog 创建的问题
assignee:cat assignee:dog分配给 catdog 的问题
commenter:cat commenter:dogcatdog 评论过的问题
involves:cat involves:dog“涉及” catbob 的问题
team:animal/white-cat team:animal/black-dog提及 animal/white-catanimal/black-dog 的问题

involves 意味着 mentionauthorassigneecommenter

存储库和组织

问题
repo:cat/jump repo:dog/runcat/jumpdog/run 中的问题
org:electron user:cat user:dogelectroncatdog 中的问题

orguser 相同

属性

问题
repo:cat/jump milestone:v1.0.0 milestone:v1.0.1cat/jump 中附加到 v1.0.0v1.0.1 的问题
repo:cat/jump label:bug label:blockercat/jump 中附加了 bug blocker 的问题
electron OR atomshell包含 electronatomshell 的问题

审查状态

问题
is:pr review:requiredcat/jump 中需要审查的问题
is:pr review-requested:cat请求 cat 审查的问题。
但这些问题尚未被审查。
is:pr reviewed-by:catcat 审查的问题

通过查看这些,您可能已经注意到,流可以使用 GitHub 的搜索查询。有关如何使用流和搜索查询的详细信息,请参阅以下 URL。

Jasper 还具有未读问题管理、未读评论管理、标记星标、通知更新、过滤问题、键盘快捷键等功能。

Jasper 是付费产品吗?它要多少钱?

Jasper 的价格为 12 美元。但是您可以使用 免费试用版 30 天。

你为什么选择在 Electron 上构建 Jasper?

我喜欢 Electron 的以下方面

  • 可以使用 JavaScript/CSS/HTML 开发应用程序。
  • 可以为 Windows、Mac 和 Linux 平台构建应用程序。
  • Electron 正在积极开发,并且拥有庞大的社区。

这些功能可以实现快速简单的桌面应用程序开发。太棒了!如果您有任何产品想法,您应该考虑使用 Electron。

在开发 Jasper 时您遇到过哪些挑战?

我很难弄清楚“流”的概念。起初,我考虑使用 GitHub 的 Notifications API。但我注意到它不支持某些用例。之后,我考虑使用 Issues APIPull Requests API 以及 Notification API。但它始终没有达到我想要的效果。然后在思考各种方法的过程中,我意识到轮询 GitHub 的 Search API 可以提供最大的灵活性。我花了一个月的时间进行实验才达到这一点,然后在两天内使用流概念实现了 Jasper 的原型。

注意:轮询最多限制为每 10 秒一次。这对于 GitHub API 的限制来说是足够可以接受的。

下一步是什么?

我计划开发以下功能

  • 过滤流:流具有一些过滤流,用于过滤流中的问题。它就像 SQL 的视图一样。
  • 多个帐户:您将能够同时使用 github.com 和 GHE
  • 提高性能:目前,在 WebView 中加载问题的速度比普通浏览器慢。

在 Twitter 上关注 @jasperappio 获取更新。

本周项目:WebTorrent

·9 分钟阅读

本周,我们采访了 @feross@dcposch,讨论了 WebTorrent,这是一款基于 Web 的 torrent 客户端,它将用户连接在一起,形成一个分布式的、去中心化的浏览器到浏览器网络。


什么是 WebTorrent?

WebTorrent 是第一个在浏览器中工作的 torrent 客户端。它完全用 JavaScript 编写,可以使用 WebRTC 进行点对点传输。无需浏览器插件、扩展程序或安装。

通过使用开放的 Web 标准,WebTorrent 将网站用户连接在一起,形成一个分布式的、去中心化的浏览器到浏览器网络,以实现高效的文件传输。

您可以在这里查看 WebTorrent 的实际演示:webtorrent.io

webtorrent homepage

这有什么酷的?

想象一下一个像 YouTube 这样的视频网站,但访问者可以帮助托管网站的内容。使用 WebTorrent 驱动的网站的人越多,它就越快、越有弹性。

浏览器对浏览器之间的通信无需中间人,让人们可以按照自己的意愿进行交流。不再有客户端/服务器模式,而是一个由所有对等方组成的网络,人人平等。WebTorrent 是实现 Web 去中心化的第一步。

Electron 在其中扮演什么角色?

大约一年前,我们决定构建 WebTorrent Desktop,这是一个作为桌面应用程序运行的 WebTorrent 版本。

WebTorrent Desktop player window

我们创建 WebTorrent Desktop 的原因有三个:

  1. 我们想要一个干净、轻量级、无广告的开源 torrent 应用程序。
  2. 我们想要一个具有良好流媒体支持的 torrent 应用程序。
  3. 我们需要一个连接 BitTorrent 和 WebTorrent 网络的“混合客户端”。

如果我已经在 Web 浏览器中下载 torrent,为什么还需要桌面应用程序?

首先,简单介绍一下 WebTorrent 的设计背景。

webtorrent desktop logo

早期,BitTorrent 使用 TCP 作为其传输协议。后来,uTP 出现,承诺比 TCP 更好的性能和额外的优势。每个主流 torrent 客户端最终都采用了 uTP,如今您可以使用 BitTorrent 通过任何一种协议进行传输。WebRTC 协议是下一个合乎逻辑的步骤。它带来了与 Web 浏览器互操作的希望——一个由所有桌面 BitTorrent 客户端和数百万 Web 浏览器组成的大型 P2P 网络。

“Web 对等方”(在 Web 浏览器中运行的 torrent 对等方)通过添加数百万新的对等方并将其传播到数十个新的用例,使 BitTorrent 网络更加强大。WebTorrent 尽可能遵循 BitTorrent 规范,以便现有 BitTorrent 客户端可以轻松添加对 WebTorrent 的支持。

Vuze 这样的 torrent 应用程序已经支持 Web 对等方,但我们不想等待其他应用程序添加支持。因此,基本上,WebTorrent Desktop 是我们加速采用 WebTorrent 协议的方式。 通过创建一个人们真正想使用的超棒的 torrent 应用程序,我们可以增加网络中可以与 Web 对等方(即网站上的用户)共享 torrent 的对等方数量。

除了人们已经知道的功能之外,torrent 还有哪些有趣的用例?

WebTorrent 最令人兴奋的用途之一是对等辅助交付。像 维基百科互联网档案馆 这样的非营利项目可以通过让访问者做出贡献来减少带宽和托管成本。流行的内容可以通过浏览器到浏览器的方式快速且廉价地提供。很少访问的内容可以从原始服务器通过 HTTP 可靠地提供。

实际上,互联网档案馆已经更新了他们的 torrent 文件,使其与 WebTorrent 完美兼容。因此,如果您想在您的网站上嵌入互联网档案馆的内容,您可以通过一种方式来降低互联网档案馆的托管成本,从而使他们能够将更多资金用于实际的网络归档!

从 CDN 到 P2P 上的应用程序交付,还有一些令人兴奋的商业用例。

您最喜欢使用 WebTorrent 的项目有哪些?

gaia app screenshot

使用 WebTorrent 构建的最酷的东西,毫无疑问,可能是 盖亚 3D 星图。这是一个流畅的银河系 3D 交互式模拟。数据直接从 torrent 在您的浏览器中加载。在我们的星系中飞行并意识到与浩瀚的宇宙相比,我们人类是多么渺小,这令人敬畏。

您可以在 Torrenting The Galaxy 中了解它的制作过程,这是一篇博文,作者 Charlie Hoey 解释了他如何使用 WebGL 和 WebTorrent 构建星图。

brave logo

我们也是 Brave 的忠实粉丝。Brave 是一款自动阻止广告和跟踪器的浏览器,旨在使 Web 更快、更安全。Brave 最近添加了 torrent 支持,因此您可以无需使用单独的应用程序即可查看传统的 torrent。该功能由 WebTorrent 提供支持。

因此,就像大多数浏览器可以呈现 PDF 文件一样,Brave 可以呈现磁力链接和 torrent 文件。它们只是浏览器本身原生支持的另一种类型的内容。

Brave 的联合创始人之一实际上是 JavaScript 的创建者 Brendan Eich,而我们正是用 JavaScript 编写的 WebTorrent,所以我们认为 Brave 选择集成 WebTorrent 非常酷。

为什么您选择在 Electron 上构建 WebTorrent Desktop?

WebTorrent Desktop main window

有一种说法认为 Electron 应用程序“臃肿”,因为它们在每个应用程序中都包含整个 Chrome 内容模块。在某些情况下,这部分是正确的(Electron 应用程序安装程序通常约为 40MB,而特定于操作系统的应用程序安装程序通常约为 20MB)。

但是,对于 WebTorrent Desktop 而言,我们在正常操作过程中几乎使用了所有 Electron 功能和许多 Chrome 功能。如果我们想为每个平台从头开始实现这些功能,那么构建我们的应用程序将花费数月甚至数年的时间,或者我们只能为单个平台发布。

为了让您了解一下,我们使用了 Electron 的 dock 集成(显示下载进度)、菜单栏集成(在后台运行)、协议处理程序注册(打开磁力链接)、电源节能阻止程序(防止在视频播放期间进入睡眠状态)和 自动更新程序。至于 Chrome 功能,我们使用了许多:<video> 标签(播放许多不同的视频格式)、<track> 标签(用于隐藏字幕支持)、拖放支持和 WebRTC(在原生应用程序中使用并非易事)。

更不用说:我们的 torrent 引擎是用 JavaScript 编写的,并且假定存在许多 Node API,特别是用于 TCP 和 UDP 套接字支持的 require('net')require('dgram')

基本上,Electron 正是我们所需要的,并且它具有我们在创纪录的时间内交付一个可靠、完善的应用程序所需的准确功能集。

您最喜欢 Electron 的哪些方面?

WebTorrent 库已经作为一个开源的业余项目开发了两年。我们用了四个星期的时间制作了 WebTorrent Desktop。 Electron 是我们能够如此快速地构建和交付我们的应用程序的主要原因。

正如 Node.js 使服务器编程对一代使用 jQuery 的前端程序员来说变得容易上手一样,Electron 使熟悉 Web 或 Node.js 开发的任何人都可以进行原生应用程序开发。Electron 非常强大。

网站和桌面客户端是否共享代码?

是的,webtorrent npm 包可以在 Node.js、浏览器和 Electron 中使用。完全相同的代码可以在所有环境中运行——这就是 JavaScript 的美妙之处。它是当今的通用运行时。Java Applets 承诺“一次编写,随处运行”应用程序,但由于多种原因,该愿景从未真正实现。Electron 比任何其他平台都更接近该理想。

在构建 WebTorrent 时,您遇到过哪些挑战?

在应用程序的早期版本中,我们很难使 UI 具有高性能。我们将 torrent 引擎放在绘制主应用程序窗口的同一个渲染器进程中,可以预见的是,每当 torrent 引擎出现密集的 CPU 活动(例如,验证从对等方接收到的 torrent 片段)时,都会导致运行缓慢。

我们通过将 torrent 引擎移动到第二个不可见的渲染器进程来解决此问题,我们通过 IPC 与其通信。这样,如果该进程短暂地使用了大量的 CPU,UI 线程将不会受到影响。流畅的滚动和动画非常令人满意。

注意:我们不得不将 torrent 引擎放在渲染器进程中,而不是“主”进程中,因为我们需要访问 WebRTC(仅在渲染器中可用)。

Electron 应该在哪些方面进行改进?

我们很希望看到关于如何构建和发布生产就绪应用的更完善的文档,特别是关于代码签名和自动更新等棘手主题。我们不得不通过深入研究源代码和在 Twitter 上四处打听来学习最佳实践!

WebTorrent Desktop 完成了吗?如果没有,接下来会推出什么?

我们认为当前版本的 WebTorrent Desktop 非常出色,但总有改进的空间。我们目前正在努力改进润色、性能、字幕支持和视频编解码器支持。

如果您有兴趣参与该项目,请查看我们的 GitHub 页面

是否有其他开发者可能会觉得有用的 Electron 开发技巧?

WebTorrent Desktop 的贡献者之一 Feross 最近在阿根廷 NodeConf 上发表了题为 “真实世界的 Electron:使用 JavaScript 构建跨平台桌面应用” 的演讲,其中包含有关发布精美 Electron 应用的有用技巧。如果您处于拥有基本可工作的应用并试图将其提升到更高的润色和专业水平的阶段,那么该演讲尤其有用。

在此观看:

幻灯片在此:

另一位 WebTorrent 贡献者 DC 撰写了 一份可以使你的应用感觉精致和原生的事项清单。它带有代码示例,并涵盖了诸如 macOS Dock 集成、拖放、桌面通知以及确保你的应用快速加载等内容。

触控栏支持

·3 分钟阅读

Electron 1.6.3 beta 版本包含对 macOS Touch Bar 的初始支持。


新的 Touch Bar API 允许你添加按钮、标签、弹出窗口、颜色选择器、滑块和间隔符。这些元素可以动态更新,并且在交互时也会发出事件。

这是此 API 的第一个版本,因此它将在接下来的几个 Electron 版本中不断发展。请查看发行说明以获取进一步的更新,并为任何问题或缺少的功能打开 issue

你可以通过 npm install electron@beta 安装此版本,并在 TouchBarBrowserWindow Electron 文档中了解更多信息。

非常感谢 @MarshallOfSound 为 Electron 做出的贡献。🎉

Touch Bar 示例

Touch Bar Gif

下面是一个在 Touch Bar 中创建一个简单的老虎机游戏的示例。它演示了如何创建 Touch Bar、设置项目样式、将其与窗口关联、处理按钮单击事件以及动态更新标签。

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

const { TouchBarButton, TouchBarLabel, TouchBarSpacer } = TouchBar;

let spinning = false;

// Reel labels
const reel1 = new TouchBarLabel();
const reel2 = new TouchBarLabel();
const reel3 = new TouchBarLabel();

// Spin result label
const result = new TouchBarLabel();

// Spin button
const spin = new TouchBarButton({
label: '🎰 Spin',
backgroundColor: '#7851A9',
click: () => {
// Ignore clicks if already spinning
if (spinning) {
return;
}

spinning = true;
result.label = '';

let timeout = 10;
const spinLength = 4 * 1000; // 4 seconds
const startTime = Date.now();

const spinReels = () => {
updateReels();

if (Date.now() - startTime >= spinLength) {
finishSpin();
} else {
// Slow down a bit on each spin
timeout *= 1.1;
setTimeout(spinReels, timeout);
}
};

spinReels();
},
});

const getRandomValue = () => {
const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀'];
return values[Math.floor(Math.random() * values.length)];
};

const updateReels = () => {
reel1.label = getRandomValue();
reel2.label = getRandomValue();
reel3.label = getRandomValue();
};

const finishSpin = () => {
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size;
if (uniqueValues === 1) {
// All 3 values are the same
result.label = '💰 Jackpot!';
result.textColor = '#FDFF00';
} else if (uniqueValues === 2) {
// 2 values are the same
result.label = '😍 Winner!';
result.textColor = '#FDFF00';
} else {
// No values are the same
result.label = '🙁 Spin Again';
result.textColor = null;
}
spinning = false;
};

const touchBar = new TouchBar([
spin,
new TouchBarSpacer({ size: 'large' }),
reel1,
new TouchBarSpacer({ size: 'small' }),
reel2,
new TouchBarSpacer({ size: 'small' }),
reel3,
new TouchBarSpacer({ size: 'large' }),
result,
]);

let window;

app.once('ready', () => {
window = new BrowserWindow({
frame: false,
titleBarStyle: 'hidden-inset',
width: 200,
height: 200,
backgroundColor: '#000',
});
window.loadURL('about:blank');
window.setTouchBar(touchBar);
});

本周项目:Voltra

·6 分钟阅读

本周,我们与 Aprile ElcichPaolo Fragomeni 会面,讨论了由 Electron 驱动的音乐播放器 Voltra。


什么是 Voltra?

Voltra 是一款为想要拥有自己音乐的人们设计的音乐播放器。它也是一个商店,您可以在其中根据您已经拥有的音乐发现和购买新音乐。它是无广告的,并且可以跨桌面和移动平台使用。它也不会监视您。

voltra-artistview

Voltra 适合谁?

任何听音乐的人。

是什么促使您创建 Voltra?

广播一直拥有大量的听众。它正在从无线电波转向互联网。现在你可以点播租用音乐——这是一种广播复兴!因此出现了很多新产品和服务,但流媒体广播仍然让其他人控制着你的音乐和你体验音乐的方式。

我们想要一个完全专注于你拥有的音乐的产品。它可以让你轻松地直接从艺术家或唱片公司发现和购买新音乐。

有免费版本吗?

桌面播放器是完全免费的。销售你的音乐也是免费的!我们不以广告为支持。

由于该应用是免费的,我们可能会在以后开源它。目前我们没有带宽来管理它。我们对功能以及我们希望采取的方向也有非常具体的想法。我们有一个活跃的 Beta 社区,我们非常重视反馈。

你们如何赚钱?

我们有高级功能!

我们的 Voltra 音频存档 是一项专为音乐设计的云备份服务。我们不压缩或共享数据块。您的音乐收藏会为您进行物理备份。

对于艺术家和唱片公司,我们的 Pro 会员资格 提供工具来帮助他们接触更多相关的受众,例如分析和专业艺术家网页。

Voltra 有什么不同?

设计和可用性对我们来说非常重要。我们希望为听众提供一种无干扰的聆听体验!市面上有一些有趣的音乐播放器和商店。但其中许多比他们的创造者意识到的更高级,更难使用。我们希望使 Voltra 对尽可能多的人可用。

我们也不会从艺术家或唱片公司那里抽成。这对我们来说是一个关键的区别。这真的很重要,因为它降低了艺术家将他们的音乐推向市场的门槛。

你们做出了一些什么样的设计和技术决策?

在设计 Voltra 时,我们考虑了来自原生应用程序和 Web 的 UI 约定,我们还考虑了很多我们可以删除的东西。我们有一个活跃的私人 Beta 小组,他们在过去几个月里给了我们重要的反馈。

我们发现专辑封面和摄影对人们来说非常重要。许多播放器只是文件列表。拥有实体专辑的酷之处之一是专辑封面,我们希望在 Voltra 桌面应用程序中强调这一点。

voltra-albumview

我们还确保不破坏人们的文件。我们使用文件监视,因此你可以将文件放在你想要的任何位置,并且我们不会为你重命名或移动它们。我们有一个嵌入式数据库来跟踪受监视目录的状态,以便我们可以跟踪新内容,即使该进程没有运行。

在构建 Voltra 时,你们面临哪些挑战?

我们花费大量时间专注于性能。我们从框架开始,但转而使用 vanilla JavaScript。根据我们的经验,它们提供的通用抽象会超过它们引入的性能损失和仪式感。

在这一点上,我们很好地处理了非常大的集合。大型集合意味着可能存在数万张图像!直接从渲染进程使用 Node.js 的文件系统模块使得基于 DOM 事件快速延迟加载和卸载大量图像变得非常容易。

通常,setImmediaterequestIdleCallback 一直是执行大量处理同时保持 UI 响应的关键工具。更具体地说,将 CPU 密集型任务分配到单独的进程中确实有助于保持用户界面的响应性。例如,我们将实际的音频上下文移动到单独的进程中,通过 IPC 与之通信,以避免来自繁忙 UI 的潜在中断。

你们为什么选择在 Electron 上构建 Voltra?

浏览器的沙箱对我们的应用来说限制太多。但我们也在开发 Web 播放器。因此,我们可以在两个实现之间共享几乎 100% 的代码,这是一个巨大的胜利。

我们实际上是从使用 Swift 构建原生应用程序开始的。我们发现的主要问题是我们重新发明了很多东西。Web 拥有世界上最大的开源生态系统。所以我们很快就切换到了 Electron。

此外,最重要的是,使用 Electron 你只需开发一次,它就应该能在所有主流平台上“开箱即用™”。虽然不能保证,但为每个平台进行原生编码的成本绝对超过了 Electron 引入的任何其他成本。

您最喜欢 Electron 的哪些方面?

GTD!: 将 Node.js 的网络堆栈和 Chromium 的展示层打包在一起,是完成工作的完美组合。

能力: 它只是 Web 技术栈,所以我们整个团队都能参与到产品的实际构建中。

社区: 这里有一个组织严密的社区,他们知道如何有效地沟通!我们对在这种支持下进行开发感到非常棒。

Electron 在哪些方面可以改进?

我们希望看到 Electron 支持一个统一的打包工具。打包工具对于 Electron 的重要性,就像包管理器对于 Node 的重要性一样。用户领域存在多个打包工具,每个都有其有趣的功能,但也都有各自的错误。社区达成共识将有助于引导贡献者投入的精力。

下一步是什么?

我们目前正在开发一款移动应用,并与艺术家和唱片公司合作,将他们的音乐添加到 Voltra 商店。嘿!如果你是艺术家或唱片公司,立即注册!我们计划在达到 1000 万首曲目的目标后开放商店。

Electron 内部:将 Chromium 构建为库

·7 分钟阅读

Electron 基于 Google 的开源项目 Chromium,该项目不一定是为了被其他项目使用而设计的。本文介绍了如何将 Chromium 构建为 Electron 使用的库,以及构建系统多年来的演变过程。


使用 CEF

Chromium Embedded Framework (CEF) 是一个将 Chromium 转化为库的项目,并基于 Chromium 的代码库提供稳定的 API。Atom 编辑器和 NW.js 的早期版本都使用了 CEF。

为了维护稳定的 API,CEF 隐藏了 Chromium 的所有细节,并用自己的接口包装了 Chromium 的 API。因此,当我们需要访问底层 Chromium API 时,例如将 Node.js 集成到网页中,CEF 的优点反而成了阻碍。

所以最终,Electron 和 NW.js 都转向直接使用 Chromium 的 API。

作为 Chromium 的一部分进行构建

尽管 Chromium 官方不支持外部项目,但其代码库是模块化的,并且很容易基于 Chromium 构建一个最小化的浏览器。提供浏览器界面的核心模块称为内容模块。

要使用内容模块开发项目,最简单的方法是将该项目构建为 Chromium 的一部分。这可以通过首先检出 Chromium 的源代码,然后将该项目添加到 Chromium 的 DEPS 文件中来实现。

NW.js 和 Electron 的早期版本都是使用这种方式进行构建的。

缺点是,Chromium 是一个非常庞大的代码库,需要非常强大的机器才能构建。对于普通的笔记本电脑,这可能需要 5 个多小时。因此,这大大影响了可以为项目做出贡献的开发人员数量,并且也使开发速度变慢。

将 Chromium 构建为单个共享库

作为内容模块的用户,在大多数情况下 Electron 不需要修改 Chromium 的代码,因此改进 Electron 构建的一个显而易见的方法是将 Chromium 构建为共享库,然后在 Electron 中与之链接。这样,开发人员在为 Electron 做出贡献时,不再需要构建 Chromium 的所有内容。

libchromiumcontent 项目由 @aroben 为此目的创建。它将 Chromium 的内容模块构建为共享库,然后提供 Chromium 的头文件和预构建的二进制文件供下载。libchromiumcontent 初始版本的代码可以在此链接中找到。

brightray 项目也是 libchromiumcontent 的一部分,它在内容模块周围提供了一个薄层。

通过一起使用 libchromiumcontent 和 brightray,开发人员可以快速构建浏览器,而无需深入了解构建 Chromium 的细节。并且它消除了构建项目对快速网络和强大机器的需求。

除了 Electron 之外,还有其他基于 Chromium 的项目以这种方式构建,例如Breach 浏览器

过滤导出的符号

在 Windows 上,一个共享库可以导出的符号数量有限制。随着 Chromium 代码库的增长,libchromiumcontent 中导出的符号数量很快就超过了限制。

解决方案是在生成 DLL 文件时过滤掉不需要的符号。它的工作方式是向链接器提供一个 .def 文件,然后使用脚本来判断命名空间下的符号是否应该导出

通过采用这种方法,尽管 Chromium 不断添加新的导出符号,libchromiumcontent 仍然可以通过剥离更多的符号来生成共享库文件。

组件构建

在讨论 libchromiumcontent 中采取的后续步骤之前,首先介绍 Chromium 中组件构建的概念是很重要的。

作为一个庞大的项目,在构建时,Chromium 中的链接步骤需要很长时间。通常,当开发人员进行少量更改时,可能需要 10 分钟才能看到最终输出。为了解决这个问题,Chromium 引入了组件构建,它将 Chromium 中的每个模块构建为单独的共享库,因此最终链接步骤花费的时间变得不明显。

发布原始二进制文件

随着 Chromium 的持续增长,Chromium 中导出的符号太多了,即使是内容模块和 Webkit 的符号也超过了限制。仅通过剥离符号是不可能生成可用的共享库的。

最后,我们不得不发布 Chromium 的原始二进制文件,而不是生成单个共享库。

如前所述,Chromium 中有两种构建模式。由于发布原始二进制文件,我们必须在 libchromiumcontent 中发布两种不同的二进制文件分发。一种称为 static_library 构建,其中包括 Chromium 正常构建生成的每个模块的所有静态库。另一种是 shared_library,其中包括组件构建生成的每个模块的所有共享库。

在 Electron 中,Debug 版本与 libchromiumcontent 的 shared_library 版本链接,因为它下载量小,并且在链接最终可执行文件时花费的时间很少。而 Electron 的 Release 版本与 libchromiumcontent 的 static_library 版本链接,因此编译器可以生成对调试很重要的完整符号,并且链接器可以进行更好的优化,因为它知道需要哪些对象文件,而哪些不需要。

因此,对于正常的开发,开发人员只需要构建 Debug 版本,这不需要良好的网络或强大的机器。尽管 Release 版本随后需要更好的硬件才能构建,但它可以生成更好的优化二进制文件。

gn 更新

作为世界上最大的项目之一,大多数普通系统都不适合构建 Chromium,Chromium 团队开发了自己的构建工具。

早期版本的 Chromium 使用 gyp 作为构建系统,但它的速度很慢,并且其配置文件对于复杂项目来说变得难以理解。经过多年的发展,Chromium 转而使用 gn 作为构建系统,它速度更快,并且具有清晰的架构。

gn 的改进之一是引入了 source_set,它代表一组对象文件。在 gyp 中,每个模块都由 static_libraryshared_library 表示,对于 Chromium 的正常构建,每个模块都会生成一个静态库,并在最终的可执行文件中链接在一起。通过使用 gn,每个模块现在只生成一堆对象文件,并且最终的可执行文件只是将所有对象文件链接在一起,因此不再生成中间的静态库文件。

然而,这种改进给 libchromiumcontent 带来了很大的麻烦,因为 libchromiumcontent 实际上需要中间的静态库文件。

解决此问题的第一个尝试是修补 gn 以生成静态库文件,这解决了问题,但远非一个合适的解决方案。

第二个尝试是由 @alespergl 从对象文件列表中生成自定义静态库。它使用了一个技巧,首先运行一个虚拟构建来收集生成的对象文件列表,然后通过向 gn 提供列表来实际构建静态库。它只对 Chromium 的源代码进行了最小的更改,并保持了 Electron 的构建架构。

总结

如你所见,与将 Electron 构建为 Chromium 的一部分相比,将 Chromium 构建为库需要付出更大的努力,并且需要持续维护。但是,后者消除了构建 Electron 对强大硬件的要求,从而使更大范围的开发人员能够构建 Electron 并为其做出贡献。这些努力是完全值得的。