跳到主要内容

docusaurus 使用 Swizzling 魔改皮肤的各个地方

1. 背景

不管是 docusaurus 增加评论系统 还是 docusaurus 自定义404界面

其实都是用到了 docusaurus 使用Swizzling的功能,特意翻了翻 docusaurus 的官方文档,其实对此有着很详细的解释,方便我们对 docusaurus 进行魔改。

原文档链接:Swizzling

2. Swizzling

通过Swizzling我们将定制 React 组件本身,而不是它们的外观。我们将讨论 Docusaurus 中的一个核心概念:swizzling,它允许更深入的网站定制。

在实践中,swizzling 允许将主题组件与自己的实现进行交换,它有两种模式:

Ejecting: 创建原始主题组件的副本,你可以对其进行完全定制 Wrapping: 会在原始主题组件周围创建一个包装器,你可以增强

3. Swizzling 过程

3.1 总览

Docusaurus 提供了一个方便的交互式 CLI 来转换组件。通常只需记住以下命令即可:

npm run swizzle

它将在你的 src/theme 目录中生成一个新组件,看起来就像下面这个例子:

src/theme/SomeComponent.js
import React from 'react';

export default function SomeComponent(props) {
// 你可以完全自定义此实现
// 包括更改 JSX、CSS 和 React 钩子
return (
<div className="some-class">
<h1>Some Component</h1>
<p>Some component implementation details</p>
</div>
);
}

要查看 swizzle 可用的所有主题和组件,请运行

npm run swizzle -- --list

使用 --help 查看所有可用的 CLI 选项,或参考 swizzle CLI 参考文档。

删除不需要的 Swizzled 组件

如果你决定不再需要先前swizzled过的组件,只需从src/theme目录中删除其文件即可。删除组件后,请确保重新启动服务器,以确保正确反映更改。

备注

swizzling组件后,请重启开发服务器,以便 Docusaurus 刷新新组件。

宁缺毋滥

请务必了解哪些组件可以安全使用。有些组件是主题的内部实现细节。

删除不需要的 Swizzled 组件

docusaurus swizzle 只是一种帮助你自动调整组件的方法。你也可以手动创建 src/theme/SomeComponent.js 文件,Docusaurus 会自动它。该命令背后没有任何内部魔法!

3.2 Ejecting

弹出(Ejecting)主题组件是创建原始主题组件副本的过程,你可以完全自定义和覆盖该副本。

要弹出主题组件,请使用 swizzle CLI 交互式操作或 --eject 选项:

npm run swizzle [theme name] [component name] -- --eject

An example:

npm run swizzle @docusaurus/theme-classic Footer -- --eject

这将把当前 <Footer /> 组件的实现复制到你网站的rc/theme 目录中。现在,Docusaurus 将使用该 <Footer> 组件副本,而不是原始组件。

现在你可以完全重新实现 <Footer> 组件。

src/theme/Footer/index.js
import React from 'react';

export default function Footer(props) {
return (
<footer>
<h1>This is my custom site footer</h1>
<p>And it is very different from the original</p>
</footer>
);
}


注意

弹出不安全组件有时会导致复制大量内部代码,而现在你必须自行维护这些代码。

这可能会增加 Docusaurus 升级的难度,因为如果收到的道具或使用的内部主题 API 发生变化,你就需要迁移你的自定义设置。

尽可能选择封装:需要维护的代码量更少。

Re-swizzling

为了在 Docusaurus 升级后保持弹出组件的最新状态,请重新运行弹出命令并使用 git diff 比较更改。我们还建议你在文件顶部写下简短注释,解释你所做的改动,以便在重新弹出后更容易地重新应用你的改动。

3.3 Wrapping

包装主题组件是在原始主题组件周围创建一个包装器的过程,你可以对其进行**增强。

要包装主题组件,请使用 swizzle CLI 交互式操作,或使用 --wrap 选项:

npm run swizzle [theme name] [component name] -- --wrap

An example:

npm run swizzle @docusaurus/theme-classic Footer -- --wrap

这将在你网站的src/theme目录下创建一个包装器。现在,Docusaurus 将使用 <FooterWrapper> 组件,而不是原始组件。现在你可以在原始组件周围添加自定义功能。

src/theme/Footer/index.js
import React from 'react';
import Footer from '@theme-original/Footer';

export default function FooterWrapper(props) {
return (
<>
<section>
<h2>Extra section</h2>
<p>This is an extra section that appears above the original footer</p>
</section>
<Footer {...props} />
</>
);
}
What is this @theme-original thing?

Docusaurus 使用 [theme aliases] 来确定要使用的主题组件。新创建的包装器使用@theme/SomeComponent别名。@theme-original/SomeComponent "允许导入包装器阴影下的原始组件,而不会造成包装器自我导入的无限导入循环。

提示

封装主题是在现有主题周围**添加额外组件而不Ejecting主题的好方法。例如,你可以轻松地在每篇博文下添加自定义评论系统:

src/theme/BlogPostItem.js
import React from 'react';
import BlogPostItem from '@theme-original/BlogPostItem';
import MyCustomCommentSystem from '@site/src/MyCustomCommentSystem';

export default function BlogPostItemWrapper(props) {
return (
<>
<BlogPostItem {...props} />
<MyCustomCommentSystem />
</>
);
}