跳到主要内容

Docusaurus使用笔记

· 阅读需 5 分钟

Docusaurus的配置和使用,供我作为备忘。

注意

我的Docusaurus版本是3.9.2,node版本是24。

请注意,方案使用了Docusaurus的内部API,哪怕是小版本变动,都有可能出现不一致的行为。

pnpm与swizzle

我所使用的包管理器是pnpm。它的依赖管理比较严格,主打的是“附庸的附庸不是我的附庸”。需要手动 hoist 部分文件。本站源代码的.npmrc展示了解决方案。

这个问题,我当时在Docusaurus的GitHub Discussions提问。当时表达不是很好,被指出来了。但是这位slorber先生仍然耐心地回复了我。特此感谢。

.npmrc
public-hoist-pattern[]=*@docusaurus/*

构建流程

正如关于页面所说,本站使用GitHub Actions自动构建。这样本地预览一下,没问题直接git commit -m "xxx" && git pull就行了。

构建流程是vibe coding得到的,即.github/workflows/build.yml

Cusdis评论区设置

使用Cusdis的理由,见这篇Post

我配置Cusdis时,在网上搜到了这位美女的配置,很可惜是错的,BlogPostItem还笔误为BlogPoseItem:

.../website/src/theme/BlogPoseItem/index.js
import React from 'react';
import BlogPostItem from '@theme-original/BlogPostItem';
import { ReactCusdis } from 'react-cusdis'

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

<ReactCusdis
lang="zh-tw" //繁體中文
attrs={{
host: 'https://cusdis.com',
appId: "{{ app_id }}", // change to tour app ID, see step 1
pageId: "{{ PAGE_ID }}",
pageTitle: props.title,
pageUrl: 'https://peiyu.us/' + props.siteUrl, // change to your website
}}
/>

</>
);
}

她的pageId和pageUrl都没有正确获取到。{{ PAGE_ID }}是召唤不出一个唯一的页面ID的。看一下她的iframe里面的源代码即可证明这一点。看到类似不小心出错的解决方案可能会让人疑惑。我试着在她的评论区提醒。但是似乎不能正常工作。下面是正解。

危险

必须把以下内容换成你自己的,不然你的评论会出现在我的网站上!

const CusdisContainer = (
<div key={cusdisTheme}>
<ReactCusdis
lang="zh-cn"
attrs={{
host: 'https://cusdis.com',
appId: '3ae124ed-37d0-46c0-84f8-e1feec7bee8a',//换成你的
pageId: permalink,
pageTitle: title,
pageUrl: "https://lizhenyu.top" + permalink,//换成你的
theme: cusdisTheme,
}}
/>
</div>
);

只要用wrap方式把BlogPostItem swizzle出来,然后按照以下内容填写(高亮部分是自己填写的):

你wrap得到的index.tsx
import React, { type ReactNode } from 'react';
import BlogPostItem from '@theme-original/BlogPostItem';
import type BlogPostItemType from '@theme/BlogPostItem';
import type { WrapperProps } from '@docusaurus/types';
import { useBlogPost } from '@docusaurus/plugin-content-blog/client'//非公开API,用于获取元数据,比如title、permalink
import { ReactCusdis } from 'react-cusdis';//评论组件
import { useColorMode, ColorMode } from '@docusaurus/theme-common';//获取当前的颜色,支持夜间模式

type Props = WrapperProps<typeof BlogPostItemType>;

export default function BlogPostItemWrapper(props: Props): ReactNode {
const DocusaurusColorModeToCusdisTheme: Record<ColorMode, 'light' | 'dark' | 'auto'> = {
light: 'light',
dark: 'dark'
};
const { colorMode } = useColorMode();
const cusdisTheme = DocusaurusColorModeToCusdisTheme[colorMode];

const { metadata, isBlogPostPage } = useBlogPost();
const { title, permalink } = metadata;
const CusdisContainer = (//Key={cusdisTheme}是说,让这个div随着cusdisTheme的动态变化而更新。
// 不然就只能等待页面刷新后才能看见效果
<div key={cusdisTheme}>
<ReactCusdis
lang="zh-cn"
attrs={{
host: 'https://cusdis.com',
appId: '3ae124ed-37d0-46c0-84f8-e1feec7bee8a',
pageId: permalink,
pageTitle: title,
pageUrl: "https://lizhenyu.top" + permalink,
theme: cusdisTheme,
}}
/>
</div>
);
return (
<>
<BlogPostItem {...props} />
{isBlogPostPage && CusdisContainer}
</>
);
}
注意

必须在“页面内部”使用useBlogPost()钩子。不然会报错。

PS:如果你wrap了DocItem,不要在里面用useDoc(),因为那似乎是文档外部,会报错。似乎可以用props.title。我wrap的是DocItem/Footer。这样做一切正常。而直接wrap DocItem,会得到一个宽度占满中间和右边的超巨大评论区——显然并非所想要的。

同理,对于DocItem/Footer(懒得高亮了):

你 wrap 得到的 index.jsx
import React, { type ReactNode } from 'react';
import Footer from '@theme-original/DocItem/Footer';
import type FooterType from '@theme/DocItem/Footer';
import type { WrapperProps } from '@docusaurus/types';

import { ReactCusdis } from 'react-cusdis';
import { useColorMode, ColorMode } from '@docusaurus/theme-common';
import { useDoc } from '@docusaurus/plugin-content-docs/client';


type Props = WrapperProps<typeof FooterType>;

export default function FooterWrapper(props: Props): ReactNode {
// 直接从 props 中获取 metadata
const { metadata } = useDoc();

const DocusaurusColorModeToCusdisTheme: Record<ColorMode, 'light' | 'dark' | 'auto'> = {
light: 'light',
dark: 'dark'
};
const { colorMode } = useColorMode();
const cusdisTheme = DocusaurusColorModeToCusdisTheme[colorMode];

const { title, permalink } = metadata;
const CusdisContainer = (
<div key={cusdisTheme}>
<ReactCusdis
lang="zh-cn"
attrs={{
host: 'https://cusdis.com',
appId: '3ae124ed-37d0-46c0-84f8-e1feec7bee8a',
pageId: permalink,
pageTitle: title,
pageUrl: "https://lizhenyu.top" + permalink,
theme: cusdisTheme,
}}
/>
</div>
);
return (
<>

<Footer {...props} />
{CusdisContainer}
</>
);
}

草稿

设置文档头部:

draft: true