メインコンテンツへスキップ
バージョン: 3.5.2

スウィズリング

このセクションでは、Docusaurus でレイアウトをカスタマイズする方法を紹介します。

デジャヴ...?

このセクションは スタイルとレイアウト に似ていますが、今回はテーマコンポーネントの見た目ではなく、それら自体をカスタマイズする必要があります。Docusaurus の中心的なコンセプトである **スウィズリング** について説明します。これは **より深いサイトカスタマイズ** が可能です。

実際には、スウィズリングにより **テーマコンポーネントを独自のインプリメンテーションにスワップ** することが可能で、2 つのパターンがあります。

  • 抽出: 元のテーマコンポーネントの **コピー** を作成し、自由に **カスタマイズ** できます。
  • ラッピング: 元のテーマコンポーネントの周囲に **ラッパー** を作成し、 **強化** できます。
なぜスウィズリングと呼ばれるのでしょうか?

Objective-C と Swift-UI に由来しています: メソッドスウィズリング は既存のセレクタ(メソッド)の実装を変更するプロセスです。

Docusaurus でコンポーネントスウィズリングとは、テーマによって提供されるコンポーネントより優先される別のコンポーネントを提供することです。

React コンポーネントの モンキーパッチ と考えることができ、デフォルトの実装を上書きできます。Gatsby には テーマシャドウイング と呼ばれる同様のコンセプトがあります。

これについてより深く理解するには、テーマコンポーネントがどのように解決されるか を理解する必要があります。

スウィズリングプロセス

概要

Docusaurusはコンポーネントをスウィズリングするための便利な対話型CLIを提供しています。通常、次のコマンドを覚えておくだけで十分です。

npm run swizzle

src/themeディレクトリに新しいコンポーネントが生成されます。この例のようになります。

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

export default function SomeComponent(props) {
// You can fully customize this implementation
// including changing the JSX, CSS and React hooks
return (
<div className="some-class">
<h1>Some Component</h1>
<p>Some component implementation details</p>
</div>
);
}

スウィズリング可能なすべてのテーマとコンポーネントの概要を取得するには、次を実行します。

npm run swizzle -- --list

--helpを使用して、使用可能なすべてのCLIオプションを表示するか、リファレンスswizzle CLIドキュメントを参照してください。

コンポーネントをスウィズリングした後、Docusaurusに新しいコンポーネントを認識させるために開発サーバを再起動してください。

安全策を講じる

スウィズリングが安全なコンポーネントを理解していることを確認してください。一部のコンポーネントはテーマの内部実装の詳細です。

情報

docusaurus swizzleは、コンポーネントをスウィズリングするための自動化された手法にすぎません。src/theme/SomeComponent.jsファイルを自分で作成することもできます。そうするとDocusaurusによって解決されます。このコマンドの背後には内部的な魔法はありません!

取り出し

テーマコンポーネントを取り出すとは、元のテーマコンポーネントのコピーを作成することで、完全にカスタマイズして上書きすることができます。

テーマコンポーネントを取り出すには、対話型のswizzle CLIを使用するか、--ejectオプションを使用します。

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

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

これにより、現在の<Footer />コンポーネントの実装が、サイトのsrc/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>
);
}

非セーフな」コンポーネントをイジェクトすることは、場合によっては大量の内部コードをコピーすることにつながり、そのメンテナンスは自分で行う必要があります。使用される小道具や内部テーマのAPIが変更された場合、カスタマイズを移行する必要があるため、Docusaurusのアップグレードがより困難になる可能性があります。

可能な限りラッピングを優先します:メンテナンスするコードの量が少なくなります。

再スウィズル

Docusaurusのアップグレード後にイジェクトされたコンポーネントを最新の状態に保つには、イジェクトコマンドを再実行し、git diffで変更を比較します。また、ファイルの先頭に簡単なコメントを書いて変更点を説明することをお勧めします。そうすることで、再イジェクト後に変更点を簡単に再適用できます。

ラッピング

テーマコンポーネントをラッピングするとは、元のテーマコンポーネントの周りにラッパーを作成するプロセスであり、このラッパーを強化できます。

テーマコンポーネントをラッピングするには、swizzle CLIをインタラクティブに使用するか、--wrapオプションを使用します。

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

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} />
</>
);
}
この@theme-originalとは何ですか?

Docusaurusでは、テーマエイリアスを使用して、使用するテーマコンポーネントを解決します。新しく作成されたラッパーは@theme/SomeComponentエイリアスを受け取ります。@theme-original/SomeComponentにより、ラッパーが自身をインポートする無限のインポートループを作成することなく、ラッパーが影を落とす元のコンポーネントをインポートできます。

ヒント

テーマをラッピングすることは、イジェクトせずに既存のコンポーネントの周りに追加コンポーネントを追加する優れた方法です。たとえば、各ブログ記事の下にカスタムコメントシステムを簡単に追加できます。

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 />
</>
);
}

スウィズルするのは安全なものとは?

大きな力には大きな責任が伴います。

一部のテーマコンポーネントはテーマの内部実装の詳細です。Docusaurusではそれらをスウィズルできますが、危険を伴う可能性があります。

どうして危険なのでしょうか?

テーマ作者(私たちも含めて)は、コンポーネントプロパティ、名前、ファイルシステムの場所、種類などを変更して、テーマを時間の経過とともに更新する必要があるかもしれません。たとえば、nameageの2つのプロパティを受け取るコンポーネントがあるとします。しかし、リファクタリング後にpersonプロパティを受け取るようになり、上記2つのプロパティが含まれています。これら2つのプロパティを想定したコンポーネントでは、代わりにundefinedがレンダリングされます。

さらに、内部コンポーネントは単に消滅する可能性があります。SidebarというコンポーネントがDocSidebarに名前変更された場合、スウィズルされたコンポーネントは完全に無視されます。

非セーフとマークされたテーマコンポーネントは、テーマのマイナーバージョン間で下位互換性のない方法で変更される可能性があります。テーマ(またはDocusaurus)をアップグレードすると、カスタマイズが予期せず動作する場合があり、サイトが壊れることさえあります。

各テーマコンポーネントについては、swizzle CLI によりテーマの作者が宣言した3 つの異なるレベルの安全性が示されます

  • 安全: このコンポーネントは swizzle しても安全であり、その公開 API は安定しており、テーマのメジャーバージョン内では問題が発生することはありません
  • 安全でない: このコンポーネントはテーマ実装の詳細であり、swizzle するのは安全でなく、テーマのマイナーバージョン内で問題が発生する可能性があります
  • 禁止されている: swizzle CLI では、swizzle するようにはまったく設計されていないため、このコンポーネントの swizzle が防止されます

一部のコンポーネントは wrap するのは安全ですが、eject するのは安全でない場合があります

情報

安全でないコンポーネントを swizzle することを過度に恐れないでください: ただし、問題が発生する可能性があり、マイナーバージョンのアップグレードでカスタムをアップグレードする必要がある場合があることに留意してください

使用事例のレポート

安全でないコンポーネントの swizzle について強力な使用事例がある場合は、こちらで報告してくださいそうすれば、安全にできるように協力してソリューションを見つけます

どのコンポーネントを swizzle すべきですか?

理想的な結果を得るためにどのコンポーネントを swizzle すべきかを明確にすることは必ずしも容易ではありません。ほとんどのテーマコンポーネントを提供する @docusaurus/theme-classic には約100 のコンポーネントがあります!

ヒント

@docusaurus/theme-classic コンポーネントのすべてを概観するには

npm run swizzle @docusaurus/theme-classic -- --list

Swizzle する適切なコンポーネントを見つけるには、次の手順に従うことができます

  1. コンポーネントの説明一部のコンポーネントは簡潔な説明を提供しており、適切なコンポーネントを見つけるには良い方法です
  2. コンポーネント名公式テーマコンポーネントには意味的な名前が付けられているため、その名前から機能を推測できる必要があります。swizzle CLI では、コンポーネント名の部分を入力して、利用可能な選択肢を絞り込むことができます。たとえば、yarn swizzle @docusaurus/theme-classic を実行し、Doc を入力すると、ドキュメント関連のコンポーネントのみがリストされます
  3. より高レベルのコンポーネントから始めますコンポーネントは、一部のコンポーネントが他をインポートするツリーを形成します。各ルートは、ルートがレンダリングする 1 つの最上位コンポーネントと関連付けられます (ほとんどは コンテンツプラグインでのルーティング にリストされています)。たとえば、すべてのブログ投稿ページには最上位コンポーネントとして @theme/BlogPostPage があります。このコンポーネントの swizzle から開始し、コンポーネントツリーを伝ってターゲットとするものだけを表示するコンポーネントを見つけます。ただし、正しいものを見つけたら残りの swizzle をファイルの削除によって解除することを忘れないでください。そうしないと、コンポーネントを多く保守することになります
  4. テーマのソースコードを読み、賢く検索します
ご質問はこちら!

必要な効果を実現するためにどのコンポーネントをスウィズルするべきかまだ分からない場合は、サポートチャンネルのいずれかで助けを求めることができます。

最高のカスタマイズのユースケースをより深く理解したいと考えておりますので、ぜひ報告してください。

スウィズルする必要がありますか?

スウィズルは最終的に、Docusaurusの内部APIと対話する追加のReactコードを維持する必要があることを意味します。可能であれば、サイトをカスタマイズする際には以下の代替案を検討してください。

  1. CSSの使用 CSSのルールとセレクタは、多くの場合、適切なカスタマイズを実現するのに役立ちます。スタイリングとレイアウトの詳細を参照してください。
  2. 翻訳の使用 驚くかもしれませんが、翻訳は最終的には単にテキストラベルをカスタマイズする方法です。たとえば、サイトのデフォルトの言語がenの場合でも、yarn write-translations -l enを実行して、出力されたcode.jsonを編集できます。i18nチュートリアルの詳細を参照してください。
ヒント

小さく、より良く スウィズルが避けられない場合は、関連する部分のみをスウィズルし、独自に可能な限り少量のコードを維持することを優先してください。小さなコンポーネントをスウィズルすることは、アップグレード中に破壊的変更を受けるリスクが低いことを意味します。

ラッピングイジェクトよりもはるかに安全な代替手段です。

サイトを<Root>でラップする

<Root>コンポーネントは、テーマ<Layout>より上のReactツリーの一番上にレンダリングされ、決してマウント解除されません。これは、ナビゲーション全体で再初期化されるべきではない状態fulなロジック(ユーザー認証ステータス、ショッピングカートの状態など)を追加するのに最適な場所です。

src/theme/Root.jsにファイルを作成して手動でスウィズルします。

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

// Default implementation, that you can customize
export default function Root({children}) {
return <>{children}</>;
}
ヒント

React Context プロバイダをレンダリングするためにこのコンポーネントを使用します。