客户端架构
主题别名
主题通过导出一组组件来工作,例如 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
不同的组件时才创建它,即当它由多个主题提供时。我们不浪费别名!