Skip to main content

Electron 简单示例

· 4 min read

我们最近在 GitHub 总部为 Hackbright 学院(一家位于旧金山的女性编程学校)的成员举办了一场 Electron 黑客马拉松。为了帮助参会者快速上手项目,我们自己的 Kevin Sawicki 创建了一些 Electron 示例应用。

¥We recently hosted an Electron hackathon at GitHub HQ for members of Hackbright Academy, a coding school for women founded in San Francisco. To help attendees get a head start on their projects, our own Kevin Sawicki created a few sample Electron applications.


如果你是 Electron 开发新手或尚未尝试过,这些示例应用是一个很好的起点。它们代码简洁、易于阅读,并且代码包含大量注释以解释其工作原理。

¥If you're new to Electron development or haven't yet tried it out, these sample applications are a great place to start. They are small, easy to read, and the code is heavily commented to explain how everything works.

首先,请克隆此代码库:

¥To get started, clone this repository:

git clone https://github.com/electron/simple-samples

要运行以下任何应用,请切换到应用目录,安装依赖,然后启动:

¥To run any of the apps below, change into the app's directory, install dependencies, then start:

cd activity-monitor
npm install
npm start

活动监视器

¥Activity Monitor

显示 CPU 系统、用户和空闲活动时间的环形图。

¥Shows a doughnut chart of the CPU system, user, and idle activity time.

哈希

¥Hash

显示使用不同算法计算的输入文本的哈希值。

¥Shows the hash values of entered text using different algorithms.

镜像

¥Mirror

以最大化尺寸播放电脑摄像头拍摄的视频,就像照镜子一样。包含一个可选的彩虹滤镜效果,该效果使用了 CSS 动画。

¥Plays a video of the computer's camera at a maximized size like looking into a mirror. Includes an optional rainbow filter effect that uses CSS animations.

价格

¥Prices

使用 Yahoo 财经 API 显示石油、黄金和白银的当前价格。

¥Shows the current price of oil, gold, and silver using the Yahoo Finance API.

URL

在窗口中加载通过命令行传递的 URL。

¥Loads a URL passed on the command line in a window.

其他资源

¥Other Resources

我们希望这些应用能帮助你快速上手 Electron。以下是一些其他资源,可供你了解更多信息:

¥We hope these apps help you get started using Electron. Here are a handful other resources for learning more:

Electron 用户空间

· 7 min read

我们在 Electron 网站上添加了一个新的 userland 部分,以帮助用户发现构成我们蓬勃发展的开源生态系统的人员、软件包和应用。

¥We've added a new userland section to the Electron website to help users discover the people, packages, and apps that make up our flourishing open-source ecosystem.


github-contributors

用户空间的起源

¥Origins of Userland

Userland 是软件社区成员聚集在一起分享工具和创意的地方。该术语起源于 Unix 社区,当时它指的是任何在内核之外运行的程​​序,但如今它的含义更多。当今 JavaScript 社区的人们提到用户空间时,通常指的是 npm 包注册中心。大多数实验和创新都发生在这里,而 Node 和 JavaScript 语言(类似 Unix 内核)则保留了一组相对较小且稳定的核心功能。

¥Userland is where people in software communities come together to share tools and ideas. The term originated in the Unix community, where it referred to any program that ran outside of the kernel, but today it means something more. When people in today's Javascript community refer to userland, they're usually talking about the npm package registry. This is where the majority of experimentation and innovation happens, while Node and the JavaScript language (like the Unix kernel) retain a relatively small and stable set of core features.

Node 和 Electron

¥Node and Electron

与 Node 一样,Electron 也拥有少量核心 API。它们提供了开发多平台桌面应用所需的基本功能。这种设计理念使得 Electron 仍然是一个灵活的工具,而不会过度规范它的使用方式。

¥Like Node, Electron has a small set of core APIs. These provide the basic features needed for developing multi-platform desktop applications. This design philosophy allows Electron to remain a flexible tool without being overly prescriptive about how it should be used.

Userland 与 "core" 相对应,使用户能够创建和共享用于扩展 Electron 功能的工具。

¥Userland is the counterpart to "core", enabling users to create and share tools that extend Electron's functionality.

数据收集

¥Collecting data

为了更好地了解生态系统的趋势,我们分析了 15,000 个依赖 electronelectron-prebuilt 的公共 GitHub 仓库的元数据。

¥To better understand the trends in our ecosystem, we analyzed metadata from 15,000 public GitHub repositories that depend on electron or electron-prebuilt

我们使用 GitHub APIlibraries.io API 和 npm 注册表来收集有关依赖、开发依赖、依赖、软件包作者、代码库贡献者、下载次数、fork 次数、stargazer 次数等信息。

¥We used the GitHub API, the libraries.io API, and the npm registry to gather info about dependencies, development dependencies, dependents, package authors, repo contributors, download counts, fork counts, stargazer counts, etc.

然后,我们使用这些数据生成了以下报告:

¥We then used this data to generate the following reports:

过滤结果

¥Filtering Results

列出软件包、应用和代码库的报告(例如 应用依赖已加星标的应用)具有可用于筛选结果的文本输入框。

¥Reports like app dependencies and starred apps which list packages, apps, and repos have a text input that can be used to filter the results.

当你在此输入框中输入内容时,页面的 URL 会动态更新。这允许你复制代表特定用户空间数据片段的 URL,然后与他人共享。

¥As you type into this input, the URL of the page is updated dynamically. This allows you to copy a URL representing a particular slice of userland data, then share it with others.

babel

更多内容即将推出

¥More to come

第一组报告仅仅是个开始。我们将继续收集社区构建 Electron 的数据,并将新的报告添加到网站。

¥This first set of reports is just the beginning. We will continue to collect data about how the community is building Electron, and will be adding new reports to the website.

用于收集和显示这些数据的所有工具均为开源:

¥All of the tools used to collect and display this data are open-source:

如果你对如何改进这些报告有任何想法,请通过 在网站代码库中提交问题 或上述任何代码库告知我们。

¥If you have ideas about how to improve these reports, please let us know opening an issue on the website repository or any of the above-mentioned repos.

感谢 Electron 社区,是你们成就了今天的用户空间!

¥Thanks to you, the Electron community, for making userland what it is today!

证书透明度修复

· 4 min read

Electron 1.4.12 包含一个重要补丁,该补丁修复了 Chrome 上游的一个问题,即在 Electron 的底层 Chrome 库 libchromiumcontent 构建 10 周后,部分 Symantec、GeoTrust 和 Thawte SSL/TLS 证书被错误拒绝。受影响网站使用的证书没有问题,更换这些证书也无济于事。

¥Electron 1.4.12 contains an important patch that fixes an upstream Chrome issue where some Symantec, GeoTrust, and Thawte SSL/TLS certificates are incorrectly rejected 10 weeks from the build time of libchromiumcontent, Electron's underlying Chrome library. There are no issues with the certificates used on the affected sites and replacing these certificates will not help.


在 Electron 1.4.0 - 1.4.11 中,使用这些受影响证书的站点的 HTTPS 请求将在特定日期后因网络错误而失败。这会影响使用 Chrome 底层网络 API 发出的 HTTPS 请求,例如 window.fetch、Ajax 请求、Electron 的 net API、BrowserWindow.loadURLwebContents.loadURL<webview> 标签上的 src 属性等等。

¥In Electron 1.4.0 — 1.4.11 HTTPS requests to sites using these affected certificates will fail with network errors after a certain date. This affects HTTPS requests made using Chrome's underlying networking APIs such as window.fetch, Ajax requests, Electron's net API, BrowserWindow.loadURL, webContents.loadURL, the src attribute on a <webview> tag, and others.

将应用升级到 1.4.12 将避免出现这些请求失败的情况。

¥Upgrading your applications to 1.4.12 will prevent these request failures from occurring.

注意:此问题在 Chrome 53 中引入,因此 Electron 1.4.0 之前的版本不受影响。

¥Note: This issue was introduced in Chrome 53 so Electron versions earlier than 1.4.0 are not affected.

影响日期

¥Impact Dates

下表列出了 Electron 1.4 的各个版本,以及使用这些受影响证书的站点的请求开始失败的日期。

¥Below is a table of each Electron 1.4 version and the date when requests to sites using these affected certificates will start to fail.

Electron 版本影响日期
1.3.x不受影响
1.4.0已失败
1.4.1已失败
1.4.2已失败
1.4.32016 年 12 月 10 日 太平洋标准时间晚上 9:00
1.4.42016 年 12 月 10 日 太平洋标准时间晚上 9:00
1.4.52016 年 12 月 10 日 太平洋标准时间晚上 9:00
1.4.62017 年 1 月 14 日 太平洋标准时间晚上 9:00
1.4.72017 年 1 月 14 日 太平洋标准时间晚上 9:00
1.4.82017 年 1 月 14 日 太平洋标准时间晚上 9:00
1.4.92017 年 1 月 14 日 太平洋标准时间晚上 9:00
1.4.102017 年 1 月 14 日 太平洋标准时间晚上 9:00
1.4.112017 年 2 月 11 日 太平洋标准时间晚上 9:00
1.4.12不受影响

你可以通过将计算机时钟调快,然后检查 https://symbeta.symantec.com/welcome/ 是否成功加载来验证应用的生效日期。

¥You can verify your app's impact date by setting your computer's clock ahead and then check to see if https://symbeta.symantec.com/welcome/ successfully loads from it.

更多信息

¥More Information

你可以在以下位置阅读有关此主题、原始问题和修复的更多信息:

¥You can read more about this topic, the original issue, and the fix at the following places:

2016 年 9 月:新应用

· 4 min read

以下是 9 月份添加到网站的全新 Electron 应用和讲座。

¥Here are the new Electron apps and talks that were added to the site in September.


本网站已更新来自社区的新 appsmeetups拉取请求。你可以订阅 查看代码库 以获取新增内容的通知,或者如果你对网站的所有更改不感兴趣,请订阅 博客 RSS 订阅

¥This site is updated with new apps and meetups through pull requests from the community. You can watch the repository to get notifications of new additions or if you're not interested in all of the site's changes, subscribe to the blog RSS feed.

如果你开发过 Electron 应用或举办过聚会,请创建一个 拉取请求 并将其添加到网站,它将出现在下一轮总结中。

¥If you've made an Electron app or host a meetup, make a pull request to add it to the site and it will make the next roundup.

新的讲座

¥New Talks

9 月,GitHub 举办了 GitHub Universe 大会,该大会被誉为软件未来构建者的盛会。活动中有几场有趣的 Electron 演讲。

¥In September, GitHub held its GitHub Universe conference billed as the event for people building the future of software. There were a couple of interesting Electron talks at the event.

此外,如果你恰好在 12 月 5 日在巴黎,Zeke 将是 在 dotJS 2016 上发表 Electron 演讲

¥Also, if you happen to be in Paris on December 5, Zeke will be giving an Electron talk at dotJS 2016.

新应用

¥New Apps

Pexels搜索完全免费的照片并将其复制到剪贴板
时间戳更好的 macOS 菜单栏时钟,带有可自定义的日期/时间显示和日历。
Harmony音乐播放器兼容 Spotify、Soundcloud、Play Music 和本地文件
uPhoneWebRTC 桌面手机
SealTalk由融云即时通讯云服务和即时通讯 SDK 支持的即时通讯应用
Infinity一种简单的演示方法
Cycligent Git 工具为你的 Git 项目提供直观的图形用户界面
Foco使用 Foco 保持专注并提高生产力
Strawberry赢得终身食客的青睐 使用一体化餐厅软件套件,更好地了解并为他们提供服务。
Mixmax实时查看电子邮件上的每个操作,随时随地撰写。
Firebase AdminFirebase 数据管理工具
ANote简单易用的 Markdown 注释
Temps一款简洁智能的菜单栏天气应用
Amium一款让文件对话的工作协作产品
Soube简单的音乐播放器
(无)彩色下一代桌面富内容编辑器,可保存兼容 HTML 和 Markdown 主题的文档。适用于 Windows、OS X 和 Linux。
quickcalc菜单栏计算器
Forestpin Analytics面向企业的财务数据分析工具
LingREST 客户端
Shorttexts常用文本、文件夹和表情符号的快捷方式
前端盒一组前端代码生成器

Electron 的结构化 API 文档

· 6 min read

今天,我们宣布对 Electron 的文档进行一些改进。现在每个新版本都包含一个 JSON 文件,详细描述 Electron 的所有公共 API。我们创建此文件是为了让开发者能够以有趣的新方式使用 Electron 的 API 文档。

¥Today we're announcing some improvements to Electron's documentation. Every new release now includes a JSON file that describes all of Electron's public APIs in detail. We created this file to enable developers to use Electron's API documentation in interesting new ways.


架构概述

¥Schema overview

每个 API 都是一个对象,具有名称、描述、类型等属性。诸如 BrowserWindowMenu 之类的类具有描述其实例方法、实例属性、实例事件等的附加属性。

¥Each API is an object with properties like name, description, type, etc. Classes such as BrowserWindow and Menu have additional properties describing their instance methods, instance properties, instance events, etc.

以下是描述 BrowserWindow 类的架构摘录:

¥Here's an excerpt from the schema that describes the BrowserWindow class:

{
name: 'BrowserWindow',
description: 'Create and control browser windows.',
process: {
main: true,
renderer: false
},
type: 'Class',
instanceName: 'win',
slug: 'browser-window',
websiteUrl: 'https://electron.nodejs.cn/docs/api/browser-window',
repoUrl: 'https://github.com/electron/electron/blob/v1.4.0/docs/api/browser-window.md',
staticMethods: [...],
instanceMethods: [...],
instanceProperties: [...],
instanceEvents: [...]
}

这是一个方法描述的示例,在本例中是 apis.BrowserWindow.instanceMethods.setMaximumSize 实例方法:

¥And here's an example of a method description, in this case the apis.BrowserWindow.instanceMethods.setMaximumSize instance method:

{
name: 'setMaximumSize',
signature: '(width, height)',
description: 'Sets the maximum size of window to width and height.',
parameters: [{
name: 'width',
type: 'Integer'
}, {
name: 'height',
type: 'Integer'
}]
}

使用新数据

¥Using the new data

为了方便开发者在他们的项目中使用这些结构化数据,我们创建了 electron-docs-api,这是一个小型 npm 包,每当有新的 Electron 版本发布时都会自动发布。

¥To make it easy for developers to use this structured data in their projects, we've created electron-docs-api, a small npm package that is published automatically whenever there's a new Electron release.

npm install electron-api-docs --save

为了立即获得满足,请在你的 Node.js REPL 中试用该模块:

¥For instant gratification, try out the module in your Node.js REPL:

npm i -g trymodule && trymodule electron-api-docs=apis

数据如何收集

¥How the data is collected

Electron 的 API 文档遵循 ​​Electron 编码风格Electron 代码规范,因此其内容可以通过编程方式解析。

¥Electron's API documentation adheres to Electron Coding Style and the Electron Styleguide, so its content can be programmatically parsed.

electron-docs-linterelectron/electron 存储库的新开发依赖。它是一个命令行工具,可以检查所有 Markdown 文件并强制执行样式指南的规则。如果发现错误,则会列出错误并停止发布流程。如果 API 文档有效,则会创建 electron-json.api 文件,并且 已上传至 GitHub 将作为 Electron 版本的一部分。

¥The electron-docs-linter is a new development dependency of the electron/electron repository. It is a command-line tool that lints all the markdown files and enforces the rules of the styleguide. If errors are found, they are listed and the release process is halted. If the API docs are valid, the electron-json.api file is created and uploaded to GitHub as part of the Electron release.

标准 Javascript 和标准 Markdown

¥Standard Javascript and Standard Markdown

今年早些时候,Electron 的代码库已更新,所有 JavaScript 代码均使用 standard 语法检查器。Standard 的 README 总结了这一选择背后的原因:

¥Earlier this year, Electron's codebase was updated to use the standard linter for all JavaScript. Standard's README sums up the reasoning behind this choice:

采用标准风格意味着将代码清晰度和社区约定的重要性置于个人风格之上。这可能并不适用于所有项目和开发文化,但开源对新手来说可能并不友好。设置清晰、自动化的贡献者期望值,使项目更健康。

¥Adopting standard style means ranking the importance of code clarity and community conventions higher than personal style. This might not make sense for 100% of projects and development cultures, however open source can be a hostile place for newbies. Setting up clear, automated contributor expectations makes a project healthier.

我们最近还创建了 standard-markdown,用于验证文档中的所有 JavaScript 代码片段是否有效,并与代码库本身的样式一致。

¥We also recently created standard-markdown to verify that all the JavaScript code snippets in our documentation are valid and consistent with the style in the codebase itself.

这些工具共同帮助我们使用持续集成 (CI) 自动查找拉取请求中的错误。这减轻了人工代码审查的负担,并使我们对文档的准确性更有信心。

¥Together these tools help us use continuous integration (CI) to automatically find errors in pull requests. This reduces the burden placed on humans doing code review, and gives us more confidence about the accuracy of our documentation.

社区成果

¥A community effort

Electron 的文档在不断改进,这要感谢我们优秀的开源社区。截至撰写本文时,已有近 300 人为文档做出了贡献。

¥Electron's documentation is constantly improving, and we have our awesome open-source community to thank for it. As of this writing, nearly 300 people have contributed to the docs.

我们很期待看到人们如何使用这些新的结构化数据。可能的用途包括:

¥We're excited to see what people do with this new structured data. Possible uses include:

Electron 内部机制:弱引用

· 11 min read

作为一种具有垃圾收集功能的语言,JavaScript 让用户无需手动管理资源。但由于 Electron 承载着这个环境,因此必须非常小心地避免内存和资源泄漏。

¥As a language with garbage collection, JavaScript frees users from managing resources manually. But because Electron hosts this environment, it has to be very careful avoiding both memory and resources leaks.

本文介绍了弱引用的概念以及如何在 Electron 中使用它们来管理资源。

¥This post introduces the concept of weak references and how they are used to manage resources in Electron.


弱引用

¥Weak references

在 JavaScript 中,每当你将对象赋值给变量时,你都会添加对该对象的引用。只要存在对对象的引用,它就会始终保存在内存中。一旦对对象的所有引用都消失,即不再有变量存储对象,JavaScript 引擎将在下一次垃圾回收时回收内存。

¥In JavaScript, whenever you assign an object to a variable, you are adding a reference to the object. As long as there is a reference to the object, it will always be kept in memory. Once all references to the object are gone, i.e. there are no longer variables storing the object, the JavaScript engine will recoup the memory on next garbage collection.

弱引用是一种对对象的引用,它允许你获取该对象,而不会影响该对象是否被垃圾回收。当对象被垃圾回收时,你也会收到通知。这样就可以使用 JavaScript 管理资源了。

¥A weak reference is a reference to an object that allows you to get the object without effecting whether it will be garbage collected or not. You will also get notified when the object is garbage collected. It then becomes possible to manage resources with JavaScript.

以 Electron 中的 NativeImage 类为例,每次调用 nativeImage.create() API 时,都会返回一个 NativeImage 实例,该实例以 C++ 格式存储图片数据。一旦你完成实例处理并且 JavaScript 引擎 (V8) 已将对象作为垃圾回收,将调用 C++ 代码来释放内存中的图片数据,因此用户无需手动管理。

¥Using the NativeImage class in Electron as an example, every time you call the nativeImage.create() API, a NativeImage instance is returned and it is storing the image data in C++. Once you are done with the instance and the JavaScript engine (V8) has garbage collected the object, code in C++ will be called to free the image data in memory, so there is no need for users manage this manually.

另一个示例是 窗口消失问题,它直观地展示了当所有对窗口的引用都消失后,窗口是如何被垃圾回收的。

¥Another example is the window disappearing problem, which visually shows how the window is garbage collected when all the references to it are gone.

在 Electron 中测试弱引用

¥Testing weak references in Electron

由于 JavaScript 语言本身没有分配弱引用的方法,因此无法直接在原始 JavaScript 中测试弱引用。JavaScript 中唯一与弱引用相关的 API 是 WeakMap,但由于它只创建弱引用键,因此无法知道对象何时被垃圾回收。

¥There is no way to directly test weak references in raw JavaScript since the language doesn't have a way to assign weak references. The only API in JavaScript related to weak references is WeakMap, but since it only creates weak-reference keys, it is impossible to know when an object has been garbage collected.

在 Electron v0.37.8 之前的版本中,你可以使用内部 v8Util.setDestructor API 测试弱引用,该 API 会向传递的对象添加弱引用,并在对象被垃圾回收时调用回调函数:

¥In versions of Electron prior to v0.37.8, you can use the internal v8Util.setDestructor API to test weak references, which adds a weak reference to the passed object and calls the callback when the object is garbage collected:

// Code below can only run on Electron < v0.37.8.
var v8Util = process.atomBinding('v8_util');

var object = {};
v8Util.setDestructor(object, function () {
console.log('The object is garbage collected');
});

// Remove all references to the object.
object = undefined;
// Manually starts a GC.
gc();
// Console prints "The object is garbage collected".

请注意,你必须使用 --js-flags="--expose_gc" 命令开关启动 Electron 才能公开内部的 gc 函数。

¥Note that you have to start Electron with the --js-flags="--expose_gc" command switch to expose the internal gc function.

该 API 在后续版本中被移除,因为 V8 实际上不允许在析构函数中运行 JavaScript 代码,而在后续版本中这样做会导致随机崩溃。

¥The API was removed in later versions because V8 actually does not allow running JavaScript code in the destructor and in later versions doing so would cause random crashes.

remote 模块中的弱引用

¥Weak references in the remote module

除了使用 C++ 管理原生资源外,Electron 还需要弱引用来管理 JavaScript 资源。一个例子是 Electron 的 remote 模块,它是一个 远程过程调用 (RPC) 模块,允许在渲染器进程中使用主进程中的对象。

¥Apart from managing native resources with C++, Electron also needs weak references to manage JavaScript resources. An example is Electron's remote module, which is a Remote Procedure Call (RPC) module that allows using objects in the main process from renderer processes.

remote 模块面临的一个关键挑战是避免内存泄漏。当用户在渲染进程中获取远程对象时,remote 模块必须保证该对象在主进程中持续存在,直到渲染进程中的引用消失。此外,它还必须确保当渲染进程中不再引用该对象时,该对象可以被垃圾回收。

¥One key challenge with the remote module is to avoid memory leaks. When users acquire a remote object in the renderer process, the remote module must guarantee the object continues to live in the main process until the references in the renderer process are gone. Additionally, it also has to make sure the object can be garbage collected when there are no longer any reference to it in renderer processes.

例如,如果没有正确实现,以下代码会很快导致内存泄漏:

¥For example, without proper implementation, following code would cause memory leaks quickly:

const { remote } = require('electron');

for (let i = 0; i < 10000; ++i) {
remote.nativeImage.createEmpty();
}

remote 模块中的资源管理非常简单。每当请求一个对象时,都会向主进程发送一条消息,Electron 会将该对象存储在一个映射中并为其分配一个 ID,然后将该 ID 发送回渲染进程。在渲染器进程中,remote 模块将接收 ID 并将其封装到代理对象中,当代理对象被垃圾回收时,将向主进程发送一条消息以释放该对象。

¥The resource management in the remote module is simple. Whenever an object is requested, a message is sent to the main process and Electron will store the object in a map and assign an ID for it, then send the ID back to the renderer process. In the renderer process, the remote module will receive the ID and wrap it with a proxy object and when the proxy object is garbage collected, a message will be sent to the main process to free the object.

remote.require API 为例,简化的实现如下所示:

¥Using remote.require API as an example, a simplified implementation looks like this:

remote.require = function (name) {
// Tell the main process to return the metadata of the module.
const meta = ipcRenderer.sendSync('REQUIRE', name);
// Create a proxy object.
const object = metaToValue(meta);
// Tell the main process to free the object when the proxy object is garbage
// collected.
v8Util.setDestructor(object, function () {
ipcRenderer.send('FREE', meta.id);
});
return object;
};

在主进程中:

¥In the main process:

const map = {};
const id = 0;

ipcMain.on('REQUIRE', function (event, name) {
const object = require(name);
// Add a reference to the object.
map[++id] = object;
// Convert the object to metadata.
event.returnValue = valueToMeta(id, object);
});

ipcMain.on('FREE', function (event, id) {
delete map[id];
});

带有弱值的 Map

¥Maps with weak values

在之前的简单实现中,remote 模块中的每次调用都会从主进程返回一个新的远程对象,每个远程对象都代表对主进程中该对象的引用。

¥With the previous simple implementation, every call in the remote module will return a new remote object from the main process, and each remote object represents a reference to the object in the main process.

设计本身没有问题,但问题是,当多次调用接收同一个对象时,会创建多个代理对象,而对于复杂的对象,这会给内存使用和垃圾回收带来巨大的压力。

¥The design itself is fine, but the problem is when there are multiple calls to receive the same object, multiple proxy objects will be created and for complicated objects this can add huge pressure on memory usage and garbage collection.

例如,以下代码:

¥For example, the following code:

const { remote } = require('electron');

for (let i = 0; i < 10000; ++i) {
remote.getCurrentWindow();
}

它首先会占用大量内存来创建代理对象,然后占用 CPU(中央处理器)进行垃圾回收并发送 IPC 消息。

¥It first uses a lot of memory creating proxy objects and then occupies the CPU (Central Processing Unit) for garbage collecting them and sending IPC messages.

一个显而易见的优化方法是缓存远程对象:如果已存在具有相同 ID 的远程对象,则将返回先前的远程对象,而不是创建新的远程对象。

¥An obvious optimization is to cache the remote objects: when there is already a remote object with the same ID, the previous remote object will be returned instead of creating a new one.

JavaScript 核心中的 API 无法做到这一点。使用普通映射缓存对象可以防止 V8 引擎对对象进行垃圾回收,而 WeakMap 类只能将对象用作弱键。

¥This is not possible with the API in JavaScript core. Using the normal map to cache objects will prevent V8 from garbage collecting the objects, while the WeakMap class can only use objects as weak keys.

为了解决这个问题,添加了一个将值作为弱引用的 map 类型,它非常适合缓存带有 ID 的对象。现在 remote.require 看起来像这样:

¥To solve this, a map type with values as weak references is added, which is perfect for caching objects with IDs. Now the remote.require looks like this:

const remoteObjectCache = v8Util.createIDWeakMap()

remote.require = function (name) {
// Tell the main process to return the meta data of the module.
...
if (remoteObjectCache.has(meta.id))
return remoteObjectCache.get(meta.id)
// Create a proxy object.
...
remoteObjectCache.set(meta.id, object)
return object
}

请注意,remoteObjectCache 将对象存储为弱引用,因此在对象被垃圾回收时无需删除键。

¥Note that the remoteObjectCache stores objects as weak references, so there is no need to delete the key when the object is garbage collected.

原生代码

¥Native code

如果你对 Electron 中 C++ 弱引用代码感兴趣,可以在以下文件中找到:

¥For people interested in the C++ code of weak references in Electron, it can be found in following files:

setDestructor API:

createIDWeakMap API:

2016 年 8 月:新应用

· 3 min read

以下是 8 月份添加到网站的全新 Electron 应用。

¥Here are the new Electron apps that were added to the site in August.


网站已更新,包含来自社区的新 appsmeetups拉取请求。你可以订阅 查看代码库 以获取新增内容的通知,或者如果你对网站的所有更改不感兴趣,请订阅 博客 RSS 订阅

¥The site is updated with new apps and meetups through pull requests from the community. You can watch the repository to get notifications of new additions or if you're not interested in all of the site's changes, subscribe to the blog RSS feed.

如果你开发过 Electron 应用或举办过聚会,请创建一个 拉取请求 并将其添加到网站,它将出现在下一轮总结中。

¥If you've made an Electron app or host a meetup, make a pull request to add it to the site and it will make the next roundup.

新应用

¥New Apps

Code RPGifyRPG 风格编码应用
PamFax用于发送和接收传真的跨平台应用
BlankUpMarkdown 编辑器清晰度 +1
Rambox将常见的 Web 应用合二为一的免费开源消息和电子邮件应用
Gordie最适合你卡片收藏的应用
Ionic Creator更快地构建出色的移动应用
TwitchAlerts用美观的警报和通知让你的浏览者满意
Museeks一款简洁、干净且跨平台的音乐播放器
SeaPigMarkdown 到 HTML 的转换器
GroupMe非官方 GroupMe 应用
Moeditor你的通用 Markdown 编辑器
SoundnodeSoundnode App 是桌面版的 Soundcloud
QMUI WebQMUI Web Desktop 是一款基于 QMUI Web 框架的项目管理应用。
Svgsus整理、清理和转换你的 SVG
Ramme非官方 Instagram 桌面应用
InsomniaREST API 客户端
Correo适用于 Windows、macOS 和 Linux 的菜单栏/任务栏 Gmail 应用
KongDashKong Admin API 的桌面客户端
翻译编辑器用于 INTL ICU 消息的翻译文件编辑器(参见 formatjsio)
5EClient5EPlay CSGO 客户端
Theme Juice简化本地 WordPress 开发

辅助功能工具

· 3 min read

打造无障碍应用至关重要,我们很高兴为 DevtronSpectron 引入新功能,让开发者有机会让他们的应用更适合所有人。

¥Making accessible applications is important and we're happy to introduce new functionality to Devtron and Spectron that gives developers the opportunity to make their apps better for everyone.


Electron 应用中的可访问性问题与网站的可访问性问题类似,因为它们最终都是 HTML。然而,对于 Electron 应用,你无法使用在线资源进行可访问性审核,因为你的应用没有 URL 指向审核员。

¥Accessibility concerns in Electron applications are similar to those of websites because they're both ultimately HTML. With Electron apps, however, you can't use the online resources for accessibility audits because your app doesn't have a URL to point the auditor to.

这些新功能将这些审计工具引入你的 Electron 应用。你可以选择使用 Spectron 为你的测试添加审计,或者在 DevTools 中使用 Devtron 的审计功能。继续阅读工具摘要或查看我们的 无障碍文档 了解更多信息。

¥These new features bring those auditing tools to your Electron app. You can choose to add audits to your tests with Spectron or use them within DevTools with Devtron. Read on for a summary of the tools or checkout our accessibility documentation for more information.

Spectron

在测试框架 Spectron 中,你现在可以审核应用中的每个窗口和 <webview> 标签。例如:

¥In the testing framework Spectron, you can now audit each window and <webview> tag in your application. For example:

app.client.auditAccessibility().then(function (audit) {
if (audit.failed) {
console.error(audit.message);
}
});

你可以在 Spectron 文档 中阅读有关此功能的更多信息。

¥You can read more about this feature in Spectron's documentation.

Devtron

Devtron 中有一个新的辅助功能选项卡,可让你审核页面在你的应用中,对结果进行排序和筛选。

¥In Devtron there is a new accessibility tab which will allow you to audit a page in your app, sort and filter the results.

devtron screenshot

这两个工具都使用了 Google 为 Chrome 构建的 辅助功能开发者工具 库。你可以了解更多关于此库在 代码库的 wiki 上使用的可访问性审核规则的信息。

¥Both of these tools are using the Accessibility Developer Tools library built by Google for Chrome. You can learn more about the accessibility audit rules this library uses on that repository's wiki.

如果你知道其他适用于 Electron 的优秀辅助工具,请通过拉取请求将它们添加到 无障碍文档

¥If you know of other great accessibility tools for Electron, add them to the accessibility documentation with a pull request.

npm 安装 electron

· 5 min read

从 Electron 1.3.1 版本开始,你可以 npm install electron --save-dev 在你的应用中安装最新的预编译版本的 Electron。

¥As of Electron version 1.3.1, you can npm install electron --save-dev to install the latest precompiled version of Electron in your app.


npm install electron

预构建的 Electron 二进制文件

¥The prebuilt Electron binary

如果你之前开发过 Electron 应用,那么你可能接触过 electron-prebuilt 这个 npm 软件包。此软件包几乎是每个 Electron 项目不可或缺的一部分。安装后,它会检测你的操作系统并下载一个预先编译好的二进制文件,该二进制文件已编译并可在你的系统架构上运行。

¥If you've ever worked on an Electron app before, you've likely come across the electron-prebuilt npm package. This package is an indispensable part of nearly every Electron project. When installed, it detects your operating system and downloads a prebuilt binary that is compiled to work on your system's architecture.

新名称

¥The new name

Electron 的安装过程常常是新开发者的绊脚石。许多勇敢的人尝试通过运行 npm install electron 而不是 npm install electron-prebuilt 来开始开发 Electron 应用,结果却发现(通常是在经过一番困惑之后)这并不是他们想要的 electron

¥The Electron installation process was often a stumbling block for new developers. Many brave people tried to get started developing an Electron by app by running npm install electron instead of npm install electron-prebuilt, only to discover (often after much confusion) that it was not the electron they were looking for.

这是因为 npm 上已经有一个 electron 项目,它是在 GitHub 的 Electron 项目存在之前创建的。为了让新开发者更轻松、更直观地进行 Electron 开发,我们联系了现有 electron npm 软件包的所有者,询问他是否愿意让我们使用该名称。幸运的是,他是我们项目的粉丝,并同意帮助我们重新使用这个名字。

¥This was because there was an existing electron project on npm, created before GitHub's Electron project existed. To help make Electron development easier and more intuitive for new developers, we reached out to the owner of the existing electron npm package to ask if he'd be willing to let us use the name. Luckily he was a fan of our project, and agreed to help us repurpose the name.

预构建版本仍在运行

¥Prebuilt lives on

从 1.3.1 版本开始,我们已开始将 electronelectron-prebuilt 软件包同时发布到 npm。这两个包完全相同。我们选择暂时继续以两个名称发布该软件包,以免给目前在其项目中使用 electron-prebuilt 的数千名开发者带来不便。我们建议你更新 package.json 文件以使用新的 electron 依赖,但我们将继续发布 electron-prebuilt 的新版本,直到 2016 年底。

¥As of version 1.3.1, we have begun publishing electron and electron-prebuilt packages to npm in tandem. The two packages are identical. We chose to continue publishing the package under both names for a while so as not to inconvenience the thousands of developers who are currently using electron-prebuilt in their projects. We recommend updating your package.json files to use the new electron dependency, but we will continue releasing new versions of electron-prebuilt until the end of 2016.

electron-userland/electron-prebuilt 仓库将继续作为 electron npm 软件包的规范存储地。

¥The electron-userland/electron-prebuilt repository will remain the canonical home of the electron npm package.

非常感谢

¥Many thanks

我们特别感谢 @mafintosh@maxogden 以及许多其他 contributors 创建和维护 electron-prebuilt,以及他们为 JavaScript、Node.js 和 Electron 社区提供的不懈服务。

¥We owe a special thanks to @mafintosh, @maxogden, and many other contributors for creating and maintaining electron-prebuilt, and for their tireless service to the JavaScript, Node.js, and Electron communities.

感谢 @logicalparadox 允许我们在 npm 上接管 electron 软件包。

¥And thanks to @logicalparadox for allowing us to take over the electron package on npm.

更新你的项目

¥Updating your projects

我们已与社区合作,更新了受此更改影响的常用软件包。electron-packagerelectron-rebuildelectron-builder 等软件包已更新,可以使用新名称,同时继续支持旧名称。

¥We've worked with the community to update popular packages that are affected by this change. Packages like electron-packager, electron-rebuild, and electron-builder have already been updated to work with the new name while continuing to support the old name.

如果你在安装此新软件包时遇到任何问题,请在 electron-userland/electron-prebuilt 代码库中提交问题告知我们。

¥If you encounter any problems installing this new package, please let us know by opening an issue on the electron-userland/electron-prebuilt repository.

如需解决 Electron 的任何其他问题,请使用 electron/electron 代码库。

¥For any other issues with Electron, please use the electron/electron repository.

Electron 内部机制:使用 Node 作为库

· 9 min read

这是解释 Electron 内部原理的系列文章的第二篇。如果你还没有查看过有关事件循环集成的 第一篇文章,请查看。

¥This is the second post in an ongoing series explaining the internals of Electron. Check out the first post about event loop integration if you haven't already.

大多数人将 节点 用于服务器端应用,但由于 Node 拥有丰富的 API 集和蓬勃发展的社区,它也非常适合用作嵌入式库。本文解释了如何在 Electron 中将 Node 用作库。

¥Most people use Node for server-side applications, but because of Node's rich API set and thriving community, it is also a great fit for an embedded library. This post explains how Node is used as a library in Electron.


构建系统

¥Build system

Node 和 Electron 都使用 GYP 作为构建系统。如果你想在应用中嵌入 Node,你也必须将其用作构建系统。

¥Both Node and Electron use GYP as their build systems. If you want to embed Node inside your app, you have to use it as your build system too.

GYP 新手?在继续阅读本文之前,请先阅读 本指南

¥New to GYP? Read this guide before you continue further in this post.

Node 的标志

¥Node's flags

Node 源代码目录中的 node.gyp 文件描述了 Node 的构建方式,以及许多 GYP 变量,用于控制 Node 的哪些部分可用以及是否启用某些配置。

¥The node.gyp file in Node's source code directory describes how Node is built, along with lots of GYP variables controlling which parts of Node are enabled and whether to open certain configurations.

要更改构建标志,你需要在项目的 .gypi 文件中设置变量。Node 中的 configure 脚本可以为你生成一些常用配置,例如,运行 ./configure --shared 将生成一个 config.gypi,其中包含指示将 Node 构建为共享库的变量。

¥To change the build flags, you need to set the variables in the .gypi file of your project. The configure script in Node can generate some common configurations for you, for example running ./configure --shared will generate a config.gypi with variables instructing Node to be built as a shared library.

Electron 不使用 configure 脚本,因为它有自己的构建脚本。Node 的配置定义在 Electron 根源代码目录下的 common.gypi 文件中。

¥Electron does not use the configure script since it has its own build scripts. The configurations for Node are defined in the common.gypi file in Electron's root source code directory.

¥Link Node with Electron

在 Electron 中,通过将 GYP 变量 node_shared 设置为 true,Node 将被链接为共享库,因此 Node 的构建类型将从 executable 更改为 shared_library,并且包含 Node main 入口点的源代码将不会被编译。

¥In Electron, Node is being linked as a shared library by setting the GYP variable node_shared to true, so Node's build type will be changed from executable to shared_library, and the source code containing the Node's main entry point will not be compiled.

由于 Electron 使用 Chromium 自带的 V8 库,因此不会使用 Node 源代码中包含的 V8 库。这是通过将 node_use_v8_platformnode_use_bundled_v8 都设置为 false 来实现的。

¥Since Electron uses the V8 library shipped with Chromium, the V8 library included in Node's source code is not used. This is done by setting both node_use_v8_platform and node_use_bundled_v8 to false.

共享库或静态库

¥Shared library or static library

与 Node 链接时,有两种选择:你可以将 Node 构建为静态库并将其包含在最终的可执行文件中,也可以将其构建为共享库并将其与最终的可执行文件一起发布。

¥When linking with Node, there are two options: you can either build Node as a static library and include it in the final executable, or you can build it as a shared library and ship it alongside the final executable.

在 Electron 中,Node 长期以来都是作为静态库构建的。这使得构建变得简单,启用了最佳的编译器优化,并且允许 Electron 无需额外的 node.dll 文件即可分发。

¥In Electron, Node was built as a static library for a long time. This made the build simple, enabled the best compiler optimizations, and allowed Electron to be distributed without an extra node.dll file.

然而,在 Chrome 切换到使用 BoringSSL 后,情况发生了变化。BoringSSL 是 OpenSSL 的一个分支,它删除了一些未使用的 API,并更改了许多现有接口。由于 Node 仍然使用 OpenSSL,如果将符号链接在一起,编译器会由于符号冲突而生成大量链接错误。

¥However, this changed after Chrome switched to use BoringSSL. BoringSSL is a fork of OpenSSL that removes several unused APIs and changes many existing interfaces. Because Node still uses OpenSSL, the compiler would generate numerous linking errors due to conflicting symbols if they were linked together.

Electron 无法在 Node 中使用 BoringSSL,也无法在 Chromium 中使用 OpenSSL,因此唯一的选择是将 Node 构建为共享库,并在各自的组件中使用 隐藏 BoringSSL 和 OpenSSL 符号

¥Electron couldn't use BoringSSL in Node, or use OpenSSL in Chromium, so the only option was to switch to building Node as a shared library, and hide the BoringSSL and OpenSSL symbols in the components of each.

此更改给 Electron 带来了一些积极的副作用。在此更改之前,如果你使用原生模块,则无法在 Windows 上重命名 Electron 的可执行文件,因为可执行文件的名称在导入库中是硬编码的。在 Node 构建为共享库后,此限制就消失了,因为所有原生模块都链接到了 node.dll,其名称无需更改。

¥This change brought Electron some positive side effects. Before this change, you could not rename the executable file of Electron on Windows if you used native modules because the name of the executable was hard coded in the import library. After Node was built as a shared library, this limitation was gone because all native modules were linked to node.dll, whose name didn't need to be changed.

支持原生模块

¥Supporting native modules

原生模块 在 Node 中的工作方式是定义一个 Node 加载的入口函数,然后从 Node 中搜索 V8 和 libuv 的符号。这对嵌入器来说有点麻烦,因为默认情况下,在将 Node 构建为库时,V8 和 libuv 的符号是隐藏的,原生模块将无法加载,因为它们找不到这些符号。

¥Native modules in Node work by defining an entry function for Node to load, and then searching the symbols of V8 and libuv from Node. This is a bit troublesome for embedders because by default the symbols of V8 and libuv are hidden when building Node as a library and native modules will fail to load because they cannot find the symbols.

因此,为了让原生模块正常工作,V8 和 libuv 符号在 Electron 中被公开。对于 V8,此操作由 强制公开 Chromium 配置文件中的所有符号 完成。对于 libuv,它由 设置 BUILDING_UV_SHARED=1 定义 实现。

¥So in order to make native modules work, the V8 and libuv symbols were exposed in Electron. For V8 this is done by forcing all symbols in Chromium's configuration file to be exposed. For libuv, it is achieved by setting the BUILDING_UV_SHARED=1 definition.

在你的应用中启动 Node

¥Starting Node in your app

完成所有构建和链接 Node 的工作后,最后一步就是在你的应用中运行 Node。

¥After all the work of building and linking with Node, the final step is to run Node in your app.

Node 不提供太多用于嵌入到其他应用中的公共 API。通常,只需调用 node::Startnode::Init 即可启动一个新的 Node 实例。然而,如果你正在基于 Node 构建一个复杂的应用,则必须使用像 node::CreateEnvironment 这样的 API 来精确控制每个步骤。

¥Node doesn't provide many public APIs for embedding itself into other apps. Usually, you can just call node::Start and node::Init to start a new instance of Node. However, if you are building a complex app based on Node, you have to use APIs like node::CreateEnvironment to precisely control every step.

在 Electron 中,Node 以两种模式启动:独立模式在主进程中运行,类似于官方 Node 二进制文件;嵌入式模式将 Node API 插入到网页中。相关细节将在后续文章中解释。

¥In Electron, Node is started in two modes: the standalone mode that runs in the main process, which is similar to official Node binaries, and the embedded mode which inserts Node APIs into web pages. The details of this will be explained in a future post.