Client architecture
Theme aliases
A theme works by exporting a set of components, e.g. Navbar
, Layout
, Footer
, to render the data passed down from plugins. Docusaurus and users use these components by importing them using the @theme
webpack alias:
import Navbar from '@theme/Navbar';
@theme
별칭은 아래와 같은 우선순위에 따라 몇 개의 디렉터리를 참조할 수 있습니다.
- 사용자의
website/src/theme
디렉터리가 가장 높은 우선순위를 가집니다. - A Docusaurus theme package's
theme
directory. - 도큐사우루스 코어에서 제공하는 대체 컴포넌트(거의 사용할 일은 없습니다)
This is called a layered architecture: a higher-priority layer providing the component would shadow a lower-priority layer, making swizzling possible. Given the following structure:
website
├── node_modules
│ └── @docusaurus/theme-classic
│ └── theme
│ └── Navbar.js
└── src
└── theme
└── Navbar.js
@theme/Navbar
가져오기를 하게 되면 website/src/theme/Navbar.js
파일이 언제나 우선순위를 가집니다. 이런 동작을 컴포넌트 바꾸기(swizzling)이라고 합니다. If you are familiar with Objective C where a function's implementation can be swapped during runtime, it's the exact same concept here with changing the target @theme/Navbar
is pointing to!
We already talked about how the "userland theme" in src/theme
can re-use a theme component through the @theme-original
alias. One theme package can also wrap a component from another theme, by importing the component from the initial theme, using the @theme-init
import.
아래 예제는 기본 테마의 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} />
);
}
Check the code of @docusaurus/theme-live-codeblock
for details.
caution
Unless you want to publish a re-usable "theme enhancer" (like @docusaurus/theme-live-codeblock
), you likely don't need @theme-init
.
It can be quite hard to wrap your mind around these aliases. Let's imagine the following case with a super convoluted setup with three themes/plugins and the site itself all trying to define the same component. Internally, Docusaurus loads these themes as a "stack".
+-------------------------------------------------+
| `website/src/theme/CodeBlock.js` | <-- `@theme/CodeBlock` always points to the top
+-------------------------------------------------+
| `theme-live-codeblock/theme/CodeBlock/index.js` | <-- `@theme-original/CodeBlock` points to the topmost non-swizzled component
+-------------------------------------------------+
| `plugin-awesome-codeblock/theme/CodeBlock.js` |
+-------------------------------------------------+
| `theme-classic/theme/CodeBlock/index.js` | <-- `@theme-init/CodeBlock` always points to the bottom
+-------------------------------------------------+
The components in this "stack" are pushed in the order of preset plugins > preset themes > plugins > themes > site
, so the swizzled component in website/src/theme
always comes out on top because it's loaded last.
@theme/*
always points to the topmost component—when CodeBlock
is swizzled, all other components requesting @theme/CodeBlock
receive the swizzled version.
@theme-original/*
always points to the topmost non-swizzled component. That's why you can import @theme-original/CodeBlock
in the swizzled component—it points to the next one in the "component stack", a theme-provided one. Plugin authors should not try to use this because your component could be the topmost component and cause a self-import.
@theme-init/*
always points to the bottommost component—usually, this comes from the theme or plugin that first provides this component. Individual plugins / themes trying to enhance code block can safely use @theme-init/CodeBlock
to get its basic version. Site creators should generally not use this because you likely want to enhance the topmost instead of the bottommost component. It's also possible that the @theme-init/CodeBlock
alias does not exist at all—Docusaurus only creates it when it points to a different one from @theme-original/CodeBlock
, i.e. when it's provided by more than one theme. We don't waste aliases!