客户端架构
主题别名
主题通过导出一组组件来工作,例如 Navbar、Layout、Footer,用于渲染从插件传递下来的数据。道格龙(Docusaurus)和用户通过使用 @theme webpack 别名来导入这些组件:
import Navbar from '@theme/Navbar';
别名 @theme 可以指向几个目录,优先级如下:
- 用户的 
website/src/theme目录,这是一个具有更高优先级的特殊目录。 - 道格龙(Docusaurus)主题包的 
theme目录。 - 道格龙(Docusaurus)核心提供的回退组件(通常不需要)。
 
这被称为_分层架构_:提供组件的更高优先级层将遮蔽较低优先级的层,从而使 swizzling 成为可能。给定以下结构:
website
├── node_modules
│   └── @docusaurus/theme-classic
│       └── theme
│           └── Navbar.js
└── src
    └── theme
        └── Navbar.js
每当导入 @theme/Navbar 时,website/src/theme/Navbar.js 都优先。这种行为称为组件 swizzling。如果你熟悉 Objective C,其中函数的实现可以在运行时交换,这里的概念与更改 @theme/Navbar 指向的目标完全相同!
我们已经讨论过 src/theme 中的"用户区主题"如何通过 @theme-original 别名重用主题组件。一个主题包也可以包装另一个主题的组件,方法是使用 @theme-init 导入从初始主题导入该组件。
下面是一个使用此功能增强默认主题 CodeBlock 组件,为其添加 react-live 展示功能的示例。
import InitialCodeBlock from '@theme-init/CodeBlock';
import React from 'react';
export default function CodeBlock(props) {
  return props.live ? (
    <ReactLivePlayground {...props} />
  ) : (
    <InitialCodeBlock {...props} />
  );
}
有关详细信息,请查看 @docusaurus/theme-live-codeblock 的代码。
除非你想发布一个可重用的"主题增强器"(如 @docusaurus/theme-live-codeblock),否则你可能不需要 @theme-init。
理解这些别名可能有些困难。让我们想象以下一个极其复杂的设置,其中有三个主题/插件和网站本身都试图定义同一个组件。在内部,道格龙(Docusaurus)将这些主题加载为一个"堆栈"。
+-------------------------------------------------+
|        `website/src/theme/CodeBlock.js`         | <-- `@theme/CodeBlock` 总是指向顶部
+-------------------------------------------------+
| `theme-live-codeblock/theme/CodeBlock/index.js` | <-- `@theme-original/CodeBlock` 指向最顶部的非 swizzle 组件
+-------------------------------------------------+
|  `plugin-awesome-codeblock/theme/CodeBlock.js`  |
+-------------------------------------------------+
|     `theme-classic/theme/CodeBlock/index.js`    | <-- `@theme-init/CodeBlock` 总是指向底部
+-------------------------------------------------+
这个"堆栈"中的组件按 预设插件 > 预设主题 > 插件 > 主题 > 网站 的顺序推送,因此 website/src/theme 中被 swizzle 的组件总是位于顶部,因为它是最后加载的。
@theme/* 总是指向最顶部的组件——当 CodeBlock 被 swizzle 时,所有其他请求 @theme/CodeBlock 的组件都会收到 swizzle 后的版本。
@theme-original/* 总是指向最顶部的非 swizzle 组件。这就是为什么你可以在 swizzle 的组件中导入 @theme-original/CodeBlock——它指向"组件堆栈"中的下一个,一个由主题提供的组件。插件作者不应尝试使用它,因为你的组件可能是最顶部的组件并导致自导入。
@theme-init/* 总是指向最底部的组件——通常,这来自最初提供此组件的主题或插件。试图增强代码块的各个插件/主题可以安全地使用 @theme-init/CodeBlock 来获取其基本版本。网站创建者通常不应使用它,因为你可能想要增强_最顶部_而不是_最底部_的组件。@theme-init/CodeBlock 别名也可能根本不存在——道格龙(Docusaurus)仅在它指向与 @theme-original/CodeBlock 不同的组件时才创建它,即当它由多个主题提供时。我们不浪费别名!