跳至主要内容

Electron 内部:消息循环集成

·4 分钟阅读

这是解释 Electron 内部原理的系列文章的第一篇。 本文介绍如何在 Electron 中将 Node 的事件循环与 Chromium 集成。


已经有很多尝试使用 Node 进行 GUI 编程,例如用于 GTK+ 绑定的 node-gui 和用于 QT 绑定的 node-qt。 但是它们都无法在生产中使用,因为 GUI 工具包有自己的消息循环,而 Node 使用 libuv 作为其自己的事件循环,并且主线程一次只能运行一个循环。 因此,在 Node 中运行 GUI 消息循环的常见技巧是在具有非常小的时间间隔的计时器中泵送消息循环,这使得 GUI 界面响应缓慢并占用大量 CPU 资源。

在 Electron 的开发过程中,我们遇到了同样的问题,尽管是以相反的方式:我们必须将 Node 的事件循环集成到 Chromium 的消息循环中。

主进程和渲染器进程

在我们深入研究消息循环集成的细节之前,我将首先解释 Chromium 的多进程架构。

在 Electron 中,有两种类型的进程:主进程和渲染器进程(实际上,这非常简化,要获得完整的视图,请参见 多进程架构)。 主进程负责 GUI 工作,例如创建窗口,而渲染器进程仅处理运行和渲染网页。

Electron 允许使用 JavaScript 来控制主进程和渲染器进程,这意味着我们必须将 Node 集成到这两个进程中。

用 libuv 替换 Chromium 的消息循环

我的第一次尝试是用 libuv 重新实现 Chromium 的消息循环。

对于渲染器进程来说很容易,因为它的消息循环仅监听文件描述符和计时器,我只需要实现与 libuv 的接口。

但是,对于主进程来说要困难得多。 每个平台都有其自己的 GUI 消息循环。 macOS Chromium 使用 NSRunLoop,而 Linux 使用 glib。 我尝试了很多技巧来从本机 GUI 消息循环中提取基础文件描述符,然后将它们馈送到 libuv 进行迭代,但是我仍然遇到了无法正常工作的边缘情况。

因此,最后我添加了一个计时器,以短时间间隔轮询 GUI 消息循环。 结果,该进程占用了恒定的 CPU 使用率,并且某些操作有很长的延迟。

在单独的线程中轮询 Node 的事件循环

随着 libuv 的成熟,现在可以采用另一种方法。

后端 fd 的概念已引入 libuv,它是一个文件描述符(或句柄),libuv 轮询该描述符以获取其事件循环。 因此,通过轮询后端 fd,可以在 libuv 中有新事件时收到通知。

因此,在 Electron 中,我创建了一个单独的线程来轮询后端 fd,并且由于我使用的是系统调用进行轮询而不是 libuv API,因此它是线程安全的。 并且每当 libuv 的事件循环中有一个新事件时,都会将消息发布到 Chromium 的消息循环,然后将在主线程中处理 libuv 的事件。

这样,我避免了修补 Chromium 和 Node,并且在主进程和渲染器进程中使用了相同的代码。

代码

您可以在 electron/atom/common/ 下的 node_bindings 文件中找到消息循环集成的实现。 它可以很容易地重复用于想要集成 Node 的项目。

更新:实现已移至 electron/shell/common/node_bindings.cc

Electron 播客

·2 分钟阅读

正在寻找 Electron 的介绍? 刚刚发布了两个新的播客,它们很好地概述了它是什么、为什么构建以及如何使用它。


立即推出

Hanselminutes:使用 Jessica Lord 创建跨平台 Electron 应用程序

Electron 只是“框架中的 Chrome”还是更多? Jessica 让 Scott 走上正确的道路,并准确地解释了 Electron 平台在您的开发世界中所处的位置。


JavaScript Air:Electron 应用程序

Electron 正在越来越成为一种使用 Web 技术构建多平台桌面应用程序的相关且流行的方式。 让我们深入了解这项很棒的技术,看看我们如何使用它来增强我们自己的体验和我们用户在桌面上的体验。


如果您正在寻找 Electron 的介绍,请先听一下。 第二个更详细地介绍了使用 Nylas 的 Evan Morikawa 提供的优秀技巧构建应用程序。

我们目前正在制作另外两个播客,它们应该在下个月发布,请关注 @ElectronJS Twitter 帐户以获取更新。

Electron 1.0

·4 分钟阅读

在过去的两年中,Electron 一直在帮助开发人员使用 HTML、CSS 和 JavaScript 构建跨平台桌面应用程序。 现在,我们很高兴与您分享我们框架和创建它的社区的一个重要里程碑。 Electron 1.0 的发布现在可以从 electronjs.org 获取。


Electron 1.0

Electron 1.0 代表了 API 稳定性和成熟度的一个重要里程碑。 此版本允许您构建在 Windows、Mac 和 Linux 上真正像原生应用程序一样运行和感觉的应用程序。 借助新的文档、新工具和新的应用程序来引导您完成 Electron API,构建 Electron 应用程序比以往任何时候都更容易。

如果您已准备好构建您的第一个 Electron 应用程序,请参阅此快速入门指南以帮助您入门。

我们很高兴看到您接下来使用 Electron 构建的内容。

Electron 的路径

我们在两年多前发布 Atom 时发布了 Electron。 Electron(当时称为 Atom Shell)是我们构建 Atom 的框架。 在那些日子里,Atom 是 Electron 提供的特性和功能背后的驱动力,因为我们努力发布最初的 Atom 版本。

现在,驱动 Electron 的是一个不断壮大的开发人员和公司社区,他们构建了从 电子邮件聊天Git 应用程序SQL 分析工具torrent 客户端机器人 的所有内容。

在过去的两年中,我们看到公司和开源项目都选择 Electron 作为其应用程序的基础。 仅在过去一年中,Electron 的下载量已超过 120 万次。 浏览 一些很棒的 Electron 应用程序,如果您的应用程序尚未在那里,请添加您自己的应用程序。

Electron downloads

Electron API 演示

除了 1.0 版本之外,我们还发布了一个新应用程序,以帮助您探索 Electron API 并了解更多关于如何使您的 Electron 应用程序感觉像原生应用程序的信息。 Electron API 演示 应用程序包含代码片段,以帮助您启动应用程序并提供有关有效使用 Electron API 的技巧。

Electron API Demos

Devtron

我们还添加了一个新扩展来帮助您调试 Electron 应用程序。 DevtronChrome 开发者工具 的一个开源扩展,旨在帮助您检查、调试和解决 Electron 应用程序的问题。

Devtron

功能

  • 需要图形,可帮助您可视化应用程序在主进程和渲染器进程中的内部和外部库依赖项
  • IPC 监视器,用于跟踪和显示应用程序中进程之间发送和接收的消息
  • 事件检查器,向您显示应用程序中在核心 Electron API(如窗口、应用程序和进程)上注册的事件和侦听器
  • App Linter,检查您的应用程序是否存在常见错误和缺少的功能

Spectron

最后,我们发布了 Spectron(Electron 应用程序的集成测试框架)的新版本。

Spectron

Spectron 3.0 全面支持整个 Electron API,允许您更快地编写测试,以验证应用程序在各种场景和环境中的行为。 Spectron 基于 ChromeDriverWebDriverIO,因此它还具有用于页面导航、用户输入和 JavaScript 执行的完整 API。

社区

Electron 1.0 是数百名开发人员共同努力的结果。 除了核心框架之外,还发布了数百个库和工具,以简化 Electron 应用程序的构建、打包和部署。

现在有一个新的 社区 页面,其中列出了许多正在开发的很棒的 Electron 工具、应用程序、库和框架。 您还可以查看 ElectronElectron Userland 组织,以查看其中一些出色的项目。

Electron 新手? 观看 Electron 1.0 介绍视频

Electron 0.37 中的新增功能

·5 分钟阅读

Electron 0.37 最近已发布,其中包括从 Chrome 47 到 Chrome 49 的重大升级以及几个新的核心 API。 最新版本带来了 Chrome 48Chrome 49 中发布的所有新功能。 这包括 CSS 自定义属性、增加的 ES6 支持、KeyboardEvent 改进、Promise 改进以及现在可在您的 Electron 应用程序中使用的许多其他新功能。


新增功能

CSS 自定义属性

如果您使用过 Sass 和 Less 等预处理语言,那么您可能熟悉变量,它允许您为颜色方案和布局等内容定义可重用的值。 变量有助于保持您的样式表 DRY 和更易于维护。

CSS 自定义属性类似于预处理变量,因为它们是可重用的,但它们也具有独特的质量,使其更加强大和灵活:它们可以使用 JavaScript 进行操作。 这种微妙但强大的功能允许动态更改视觉界面,同时仍然受益于 CSS 的硬件加速,并减少前端代码和样式表之间的代码重复。

有关 CSS 自定义属性的更多信息,请参见 MDN 文章Google Chrome 演示

CSS 变量在行动中

让我们逐步了解一个简单的变量示例,该示例可以在您的应用程序中进行实时调整。

:root {
--awesome-color: #a5ecfa;
}

body {
background-color: var(--awesome-color);
}

可以在 JavaScript 中直接检索和更改变量值

// Get the variable value ' #A5ECFA'
let color = window
.getComputedStyle(document.body)
.getPropertyValue('--awesome-color');

// Set the variable value to 'orange'
document.body.style.setProperty('--awesome-color', 'orange');

也可以从开发工具的样式部分编辑变量值,以获得快速反馈和调整

CSS properties in Styles tab

KeyboardEvent.code 属性

Chrome 48 添加了 KeyboardEvent 事件上可用的新 code 属性,该属性将是按下的物理键,与操作系统键盘布局无关。

这应该使在您的 Electron 应用程序中实现自定义键盘快捷键在不同的机器和配置中更加准确和一致。

window.addEventListener('keydown', function (event) {
console.log(`${event.code} was pressed.`);
});

查看 此示例 以查看其运行情况。

Promise 拒绝事件

Chrome 49 添加了两个新的 window 事件,允许您在拒绝的 Promise 未处理时收到通知。

window.addEventListener('unhandledrejection', function (event) {
console.log('A rejected promise was unhandled', event.promise, event.reason);
});

window.addEventListener('rejectionhandled', function (event) {
console.log('A rejected promise was handled', event.promise, event.reason);
});

查看 此示例 以查看其运行情况。

V8 中的 ES2015 更新

现在 Electron 中使用的 V8 版本包含 91% 的 ES2015。 以下是一些有趣的添加,您可以直接使用它们——无需标记或预编译器

默认参数

function multiply(x, y = 1) {
return x * y;
}

multiply(5); // 5

解构赋值

Chrome 49 添加了解构赋值,使变量和函数参数的赋值变得更加容易。

这使得 Electron 的 require 语句更简洁紧凑。

浏览器进程 Require
const { app, BrowserWindow, Menu } = require('electron');
渲染器进程 Require
const { dialog, Tray } = require('electron').remote;
其他示例
// Destructuring an array and skipping the second element
const [first, , last] = findAll();

// Destructuring function parameters
function whois({ displayName: displayName, fullName: { firstName: name } }) {
console.log(`${displayName} is ${name}`);
}

let user = {
displayName: 'jdoe',
fullName: {
firstName: 'John',
lastName: 'Doe',
},
};
whois(user); // "jdoe is John"

// Destructuring an object
let { name, avatar } = getUser();

新的 Electron API

以下是一些新的 Electron API,您可以在 Electron 版本发布说明中查看每个新的 API。

BrowserWindow上的showhide事件

当窗口显示或隐藏时,将发出这些事件。

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

let window = new BrowserWindow({ width: 500, height: 500 });
window.on('show', function () {
console.log('Window was shown');
});
window.on('hide', function () {
console.log('Window was hidden');
});

app上的platform-theme-changed事件(适用于OS X

当系统切换到深色模式主题时,会发出此事件。

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

app.on('platform-theme-changed', function () {
console.log(`Platform theme changed. In dark mode? ${app.isDarkMode()}`);
});

app.isDarkMode()(适用于OS X

如果系统处于深色模式,则此方法返回true,否则返回false

scroll-touch-beginscroll-touch-end事件到 BrowserWindow(适用于OS X

当滚轮事件阶段开始或结束时,将发出这些事件。

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

let window = new BrowserWindow({ width: 500, height: 500 });
window.on('scroll-touch-begin', function () {
console.log('Scroll touch started');
});
window.on('scroll-touch-end', function () {
console.log('Scroll touch ended');
});

在 Electron 中使用 V8 和 Chromium 功能

·2 分钟阅读

构建 Electron 应用程序意味着您只需要创建一个代码库并为一个浏览器设计,这非常方便。但由于 Electron 与 Node.jsChromium 保持同步更新,因此您还可以使用它们提供的新功能。在某些情况下,这可以消除您以前可能需要在 Web 应用程序中包含的依赖项。


有很多功能,我们将在此处介绍一些示例,但如果您有兴趣了解所有功能,您可以关注 Google Chromium 博客Node.js 变更日志。您可以在electronjs.org/#electron-versions中查看 Electron 使用的 Node.js、Chromium 和 V8 的版本。

通过 V8 支持 ES6

Electron 将 Chromium 的渲染库与 Node.js 结合在一起。两者共享相同的 JavaScript 引擎,V8。许多 ECMAScript 2015 (ES6) 功能已经内置到 V8 中,这意味着您可以在 Electron 应用程序中使用它们,而无需任何编译器。

以下是一些示例,但您还可以获得类(在严格模式下)、块作用域、Promise、类型化数组等等。请查看此列表,了解有关 V8 中 ES6 功能的更多信息。

箭头函数

findTime () => {
console.log(new Date())
}

字符串插值

var octocat = 'Mona Lisa';
console.log(`The octocat's name is ${octocat}`);

New Target

Octocat() => {
if (!new.target) throw "Not new";
console.log("New Octocat");
}

// Throws
Octocat();
// Logs
new Octocat();

数组 Includes

// Returns true
[1, 2].includes(2);

Rest 参数

// Represent indefinite number of arguments as an array
(o, c, ...args) => {
console.log(args.length);
};

Chromium 功能

感谢 Google 和贡献者为 Chromium 付出的辛勤工作,当您构建 Electron 应用程序时,您还可以使用一些很棒的功能,例如(但不限于):

请关注Google Chromium 博客,了解新版本发布时的功能,再次,您可以在此处查看 Electron 使用的 Chromium 版本。

您对什么感到兴奋?

在 Twitter 上通过@ElectronJS告诉我们您最喜欢的 V8 或 Chromium 内置功能。

Electron 1.0 中即将进行的 API 更改

·4 分钟阅读

自从 Electron 开始,追溯到它被称为 Atom-Shell 的时候,我们一直在尝试为 Chromium 的 content 模块和原生 GUI 组件提供一个不错的跨平台 JavaScript API。 这些 API 最初是非常有机地开始的,随着时间的推移,我们进行了多次更改以改进最初的设计。


现在,随着 Electron 准备发布 1.0 版本,我们想借此机会通过解决最后的 API 细节来进行更改。 下面描述的更改包含在 0.35.x 中,旧的 API 会报告弃用警告,以便您可以为未来的 1.0 版本进行更新。 Electron 1.0 不会在几个月后发布,因此您有时间在这些更改变为破坏性更改之前进行更新。

弃用警告

默认情况下,如果您正在使用已弃用的 API,则会显示警告。 要关闭它们,您可以将 process.noDeprecation 设置为 true。 要跟踪已弃用 API 用法的来源,您可以将 process.throwDeprecation 设置为 true 以抛出异常而不是打印警告,或者将 process.traceDeprecation 设置为 true 以打印弃用的跟踪。

使用内置模块的新方法

内置模块现在被分组到一个模块中,而不是分成独立的模块,因此您可以避免与其他模块冲突地使用它们。

var app = require('electron').app;
var BrowserWindow = require('electron').BrowserWindow;

旧的require('app')方法仍然支持向后兼容,但您也可以将其关闭。

require('electron').hideInternalModules();
require('app'); // throws error.

一种更简单地使用 remote 模块的方法

由于使用内置模块的方式发生了变化,我们使在渲染器进程中使用主进程侧模块变得更加容易。 您现在只需访问 remote 的属性即可使用它们。

// New way.
var app = require('electron').remote.app;
var BrowserWindow = require('electron').remote.BrowserWindow;

而不是使用长 require 链

// Old way.
var app = require('electron').remote.require('app');
var BrowserWindow = require('electron').remote.require('BrowserWindow');

拆分 ipc 模块

ipc 模块存在于主进程和渲染器进程中,并且 API 在每一侧都不同,这对于新用户来说非常令人困惑。 我们已将该模块在主进程中重命名为 ipcMain,在渲染器进程中重命名为 ipcRenderer,以避免混淆。

// In main process.
var ipcMain = require('electron').ipcMain;
// In renderer process.
var ipcRenderer = require('electron').ipcRenderer;

对于 ipcRenderer 模块,在接收消息时添加了一个额外的 event 对象,以匹配 ipcMain 模块中处理消息的方式。

ipcRenderer.on('message', function (event) {
console.log(event);
});

标准化 BrowserWindow 选项

BrowserWindow 选项基于其他 API 的选项具有不同的样式,并且由于名称中包含 - 而在 JavaScript 中有点难以使用。 它们现在已标准化为传统的 JavaScript 名称。

new BrowserWindow({ minWidth: 800, minHeight: 600 });

遵循 DOM 的 API 名称约定

Electron 中的 API 名称过去更喜欢对所有 API 名称使用 camelCase,例如 UrlURL,但 DOM 有其自己的约定,他们更喜欢 URL 而不是 Url,同时使用 Id 而不是 ID。 我们已经完成了以下 API 重命名以匹配 DOM 的样式。

  • Url 重命名为 URL
  • Csp 重命名为 CSP

由于这些更改,在使用 Electron v0.35.0 开发您的应用程序时,您会注意到很多弃用。 修复它们的简单方法是将所有 Url 实例替换为 URL

更改 Tray 的事件名称

Tray 事件名称的样式与其他模块略有不同,因此已完成重命名以使其与其他模块匹配。

  • clicked 重命名为 click
  • double-clicked 重命名为 double-click
  • right-clicked 重命名为 right-click

Electron 上的 Mac App Store 和 Windows 自动更新程序

·2 分钟阅读

最近,Electron 添加了两个令人兴奋的功能:Mac App Store 兼容版本和内置 Windows 自动更新程序。


Mac App Store 支持

v0.34.0 起,每个 Electron 版本都包含与 Mac App Store 兼容的版本。 以前,在 Electron 上构建的应用程序不符合 Apple 对 Mac App Store 的要求。 这些要求中的大多数与私有 API 的使用有关。 为了以符合要求的这种方式对 Electron 进行沙盒处理,需要删除两个模块

  • crash-reporter
  • auto-updater

此外,一些行为已更改,涉及检测 DNS 更改、视频捕获和辅助功能。 您可以在文档中阅读有关更改和将您的应用提交到 Mac App Store的更多信息。 这些分发版可以在Electron 版本页面上找到,前缀为 mas-

相关拉取请求:electron/electron#3108, electron/electron#2920

Windows 自动更新程序

在 Electron v0.34.1 中,auto-updater 模块得到了改进,以便与 Squirrel.Windows 一起使用。 这意味着 Electron 提供了在 OS X 和 Windows 上轻松自动更新您的应用程序的方法。 您可以在文档中阅读有关 设置您的应用程序以在 Windows 上自动更新的更多信息。

相关拉取请求:electron/electron#1984

Electron 中的新增功能

·4 分钟阅读

最近有一些关于 Electron 的有趣更新和演讲,这是一个综述。


来源

v0.32.0 起,Electron 现在已更新至 Chrome 45。 其他更新包括...

更好的文档

new docs

我们已经重组和标准化了文档,使其看起来更好并且更易于阅读。 还有社区贡献的文档翻译,如日语和韩语。

相关拉取请求:electron/electron#2028, electron/electron#2533, electron/electron#2557, electron/electron#2709, electron/electron#2725, electron/electron#2698, electron/electron#2649.

Node.js 4.1.0

v0.33.0 起,Electron 附带 Node.js 4.1.0。

相关拉取请求:electron/electron#2817.

node-pre-gyp

依赖于 node-pre-gyp 的模块现在可以在从源代码构建时针对 Electron 进行编译。

相关拉取请求:mapbox/node-pre-gyp#175.

ARM 支持

Electron 现在为 ARMv7 上的 Linux 提供构建。 它在 Chromebook 和 Raspberry Pi 2 等流行平台上运行。

相关问题:atom/libchromiumcontent#138, electron/electron#2094, electron/electron#366.

Yosemite 风格的无框架窗口

frameless window

@jaanus 提供的一个补丁已经合并,与其他内置 OS X 应用程序一样,允许在 OS X Yosemite 及更高版本上创建集成系统信号灯的无框架窗口。

相关拉取请求:electron/electron#2776.

Google Summer of Code 打印支持

在 Google Summer of Code 之后,我们合并了 @hokein 提供的补丁,以改进打印支持,并添加了将页面打印到 PDF 文件的功能。

相关问题:electron/electron#2677, electron/electron#1935, electron/electron#1532, electron/electron#805, electron/electron#1669, electron/electron#1835.

Atom

Atom 现在已升级到 Electron v0.30.6,运行 Chrome 44。 升级到 v0.33.0 正在 atom/atom#8779 上进行。

演讲

GitHubber Amy PalamountainNordic.js 的演讲中对 Electron 进行了精彩的介绍。 她还创建了 electron-accelerator 库。

Amy Palomountain 使用 Electron 构建原生应用程序

Atom 团队的 Ben Ogle 也在 YAPC Asia 上发表了 Electron 演讲。

Ben Ogle 使用 Web 技术构建桌面应用程序

Atom 团队成员 Kevin Sawicki 和其他人最近在 Bay Are Electron User Group 聚会上发表了关于 Electron 的演讲。 视频已经发布,以下是几个

Kevin Sawicki 的 Electron 历史

Ben Gotow 的让 Web 应用程序感觉原生

GitHub 总部的 Electron 聚会

·一分钟阅读

加入我们,9 月 29 日在 GitHub 总部参加由 Atom 团队成员 @jlord@kevinsawicki 主持的 Electron 聚会。 将会有演讲、小吃食物,以及与其他使用 Electron 做很棒事情的人闲逛和见面的时间。 我们还将有一些时间为感兴趣的人进行闪电演讲。 希望在那里见到你!


演讲

  • JiboJonathan RossFrancois Laberge 将分享他们如何使用 Electron 来动画机器人。
  • Jessica Lord 将会谈论在 Electron 上构建教学工具 Git-it
  • Tom Moor 将会谈论使用 speak.io 在 Electron 上构建视频和屏幕共享的优缺点。
  • Ben Gotow 将会预览 N1:The Nylas Mail Client,并谈论在 Electron 上开发它。

详细信息

  • 地点: GitHub HQ, 275 Brannan Street, San Francisco, CA, 94107
  • 日期: 2015 年 9 月 29 日,星期二
  • 时间: 下午 6 点 - 9 点
  • RSVP: ti.to/github-events/electron-meetup

electron-meetup-office-2

Electron 文档

·5 分钟阅读

本周,我们已将 Electron 的文档放置在 electronjs.org 上。 您可以访问 /docs/latest 获取最新的文档集。 我们也会保留旧文档的版本,因此您可以访问 /docs/vX.XX.X 获取与您使用的版本相关的文档。


您可以访问 /docs 查看可用的版本,或者访问 /docs/all 在一个页面上查看最新版本的文档(非常适合 cmd + f 搜索)。

如果您想为文档内容做出贡献,您可以在 Electron 存储库中执行此操作,文档是从该处获取的。 我们为每个小版本获取它们,并将它们添加到 Electron 网站存储库,该存储库由 Jekyll 创建。

如果您有兴趣了解更多关于我们如何将文档从一个存储库拉到另一个存储库的信息,请继续阅读以下内容。 否则,请享受 文档

技术细节

我们将文档保留在 Electron 核心存储库中。 这意味着 electron/electron 将始终具有最新版本的文档。 当发布新版本的 Electron 时,我们会将它们复制到 Electron 网站存储库 electron/electronjs.org 上。

script/docs

为了获取文档,我们运行一个脚本,它带有一个命令行界面,命令是 script/docs vX.XX.X,可以带或不带 --latest 选项(取决于你要导入的版本是否是最新版本)。我们的获取文档的脚本使用了一些有趣的 Node 模块。

测试帮助我们了解所有内容是否按预期落地。

Jekyll

Electron 网站是一个 Jekyll 站点,我们利用 Collections 功能来组织文档,结构如下:

electron.atom.io
└── _docs
├── latest
├── v0.27.0
├── v0.26.0
├── so on
└── so forth

Front matter

为了让 Jekyll 渲染每个页面,它至少需要空的 front matter。 我们将在所有页面上使用 front matter,因此在流式输出 /docs 目录时,我们会检查文件是否是 README.md 文件(在这种情况下,它会收到一个 front matter 配置),或者是否是任何其他带有 markdown 扩展名的文件(在这种情况下,它会收到略有不同的 front matter)。

每个页面都会收到这组 front matter 变量:

---
version: v0.27.0
category: Tutorial
title: 'Quick Start'
source_url: 'https://github.com/electron/electron/blob/master/docs/tutorial/quick-start.md'
---

README.md 文件会获得额外的 permalink,以便其 URL 具有 index.html 的公共根目录,而不是笨拙的 /readme/

permalink: /docs/v0.27.0/index.html

配置和重定向

在站点的 _config.yml 文件中,每次在使用 --latest 标志获取文档时,都会设置一个变量 latest_version。我们还添加了已添加到站点的所有版本的列表,以及我们希望整个文档集合使用的永久链接。

latest_version: v0.27.0
available_versions:
- v0.27.0
collections:
docs: { output: true, permalink: '/docs/:path/' }

我们站点根目录中的文件 latest.md 是空的,除了这个 front matter,它允许用户通过访问这个 URL,electron.atom.io/docs/latest,来查看最新版本文档的索引(也就是 README),而不是专门使用最新的版本号(尽管你也可以这样做)。

---
permalink: /docs/latest/
redirect_to: /docs/{{ site.data.releases[0].version }}
---

布局

docs.html 布局模板中,我们使用条件语句来显示或隐藏 header 和面包屑中的信息。

{% raw %} {% if page.category != 'ignore' %}
<h6 class="docs-breadcrumb">
{{ page.version }} / {{ page.category }} {% if page.title != 'README' %} / {{
page.title }} {% endif %}
</h6>
{% endif %} {% endraw %}

为了创建一个显示可用版本的页面,我们只需在一个文件中 (versions.md, 在站点的根目录下) 循环浏览配置中的列表。 另外,我们给这个页面一个永久链接: /docs/

{% raw %} {% for version in site.available_versions %} - [{{ version
}}](/docs/{{ version }}) {% endfor %} {% endraw %}

希望你喜欢这些技术细节!如果你有兴趣了解更多关于使用 Jekyll 构建文档站点的信息,请查看 GitHub 的文档团队如何使用 Jekyll 发布 GitHub 的文档