スウィズリング
このセクションでは、Docusaurus でレイアウトをカスタマイズする方法を紹介します。
デジャヴ...?
このセクションは スタイルとレイアウト に似ていますが、今回はテーマコンポーネントの見た目ではなく、それら自体をカスタマイズする必要があります。Docusaurus の中心的なコンセプトである **スウィズリング** について説明します。これは **より深いサイトカスタマイズ** が可能です。
実際には、スウィズリングにより **テーマコンポーネントを独自のインプリメンテーションにスワップ** することが可能で、2 つのパターンがあります。
- 抽出: 元のテーマコンポーネントの **コピー** を作成し、自由に **カスタマイズ** できます。
- ラッピング: 元のテーマコンポーネントの周囲に **ラッパー** を作成し、 **強化** できます。
なぜスウィズリングと呼ばれるのでしょうか?
Objective-C と Swift-UI に由来しています: メソッドスウィズリング は既存のセレクタ(メソッド)の実装を変更するプロセスです。
Docusaurus でコンポーネントスウィズリングとは、テーマによって提供されるコンポーネントより優先される別のコンポーネントを提供することです。
React コンポーネントの モンキーパッチ と考えることができ、デフォルトの実装を上書きできます。Gatsby には テーマシャドウイング と呼ばれる同様のコンセプトがあります。
これについてより深く理解するには、テーマコンポーネントがどのように解決されるか を理解する必要があります。
スウィズリングプロセス
概要
Docusaurusはコンポーネントをスウィズリングするための便利な対話型CLIを提供しています。通常、次のコマンドを覚えておくだけで十分です。
- npm
- Yarn
- pnpm
npm run swizzle
yarn swizzle
pnpm run swizzle
src/theme
ディレクトリに新しいコンポーネントが生成されます。この例のようになります。
- 取り出し
- ラップ
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>
);
}
import React from 'react';
import SomeComponent from '@theme-original/SomeComponent';
export default function SomeComponentWrapper(props) {
// You can enhance the original component,
// including adding extra props or JSX elements around it
return (
<>
<SomeComponent {...props} />
</>
);
}
スウィズリング可能なすべてのテーマとコンポーネントの概要を取得するには、次を実行します。
- npm
- Yarn
- pnpm
npm run swizzle -- --list
yarn swizzle --list
pnpm run swizzle --list
--help
を使用して、使用可能なすべてのCLIオプションを表示するか、リファレンスswizzle CLIドキュメントを参照してください。
コンポーネントをスウィズリングした後、Docusaurusに新しいコンポーネントを認識させるために開発サーバを再起動してください。
スウィズリングが安全なコンポーネントを理解していることを確認してください。一部のコンポーネントはテーマの内部実装の詳細です。
docusaurus swizzle
は、コンポーネントをスウィズリングするための自動化された手法にすぎません。src/theme/SomeComponent.js
ファイルを自分で作成することもできます。そうするとDocusaurusによって解決されます。このコマンドの背後には内部的な魔法はありません!
取り出し
テーマコンポーネントを取り出すとは、元のテーマコンポーネントのコピーを作成することで、完全にカスタマイズして上書きすることができます。
テーマコンポーネントを取り出すには、対話型のswizzle CLIを使用するか、--eject
オプションを使用します。
- npm
- Yarn
- pnpm
npm run swizzle [theme name] [component name] -- --eject
yarn swizzle [theme name] [component name] --eject
pnpm run swizzle [theme name] [component name] --eject
例
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic Footer -- --eject
yarn swizzle @docusaurus/theme-classic Footer --eject
pnpm run swizzle @docusaurus/theme-classic Footer --eject
これにより、現在の<Footer />
コンポーネントの実装が、サイトのsrc/theme
ディレクトリにコピーされます。Docusaurusは、この<Footer>
コンポーネントのコピーを、元のコンポーネントの代わりに使用するようになります。これで<Footer>
コンポーネントを完全に再実装できます。
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のアップグレード後にイジェクトされたコンポーネントを最新の状態に保つには、イジェクトコマンドを再実行し、git diff
で変更を比較します。また、ファイルの先頭に簡単なコメントを書いて変更点を説明することをお勧めします。そうすることで、再イジェクト後に変更点を簡単に再適用できます。
ラッピング
テーマコンポーネントをラッピングするとは、元のテーマコンポーネントの周りにラッパーを作成するプロセスであり、このラッパーを強化できます。
テーマコンポーネントをラッピングするには、swizzle CLIをインタラクティブに使用するか、--wrap
オプションを使用します。
- npm
- Yarn
- pnpm
npm run swizzle [theme name] [component name] -- --wrap
yarn swizzle [theme name] [component name] --wrap
pnpm run swizzle [theme name] [component name] --wrap
例
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic Footer -- --wrap
yarn swizzle @docusaurus/theme-classic Footer --wrap
pnpm run swizzle @docusaurus/theme-classic Footer --wrap
これにより、サイトのsrc/theme
ディレクトリにラッパーが作成されます。Docusaurusは、オリジナルではなく、<FooterWrapper>
コンポーネントを使用します。これで、元のコンポーネントの周囲にカスタマイズを追加できます。
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
により、ラッパーが自身をインポートする無限のインポートループを作成することなく、ラッパーが影を落とす元のコンポーネントをインポートできます。
テーマをラッピングすることは、イジェクトせずに既存のコンポーネントの周りに追加コンポーネントを追加する優れた方法です。たとえば、各ブログ記事の下にカスタムコメントシステムを簡単に追加できます。
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ではそれらをスウィズルできますが、危険を伴う可能性があります。
どうして危険なのでしょうか?
テーマ作者(私たちも含めて)は、コンポーネントプロパティ、名前、ファイルシステムの場所、種類などを変更して、テーマを時間の経過とともに更新する必要があるかもしれません。たとえば、name
とage
の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
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic -- --list
yarn swizzle @docusaurus/theme-classic --list
pnpm run swizzle @docusaurus/theme-classic --list
Swizzle する適切なコンポーネントを見つけるには、次の手順に従うことができます
- コンポーネントの説明一部のコンポーネントは簡潔な説明を提供しており、適切なコンポーネントを見つけるには良い方法です
- コンポーネント名公式テーマコンポーネントには意味的な名前が付けられているため、その名前から機能を推測できる必要があります。swizzle CLI では、コンポーネント名の部分を入力して、利用可能な選択肢を絞り込むことができます。たとえば、
yarn swizzle @docusaurus/theme-classic
を実行し、Doc
を入力すると、ドキュメント関連のコンポーネントのみがリストされます - より高レベルのコンポーネントから始めますコンポーネントは、一部のコンポーネントが他をインポートするツリーを形成します。各ルートは、ルートがレンダリングする 1 つの最上位コンポーネントと関連付けられます (ほとんどは コンテンツプラグインでのルーティング にリストされています)。たとえば、すべてのブログ投稿ページには最上位コンポーネントとして
@theme/BlogPostPage
があります。このコンポーネントの swizzle から開始し、コンポーネントツリーを伝ってターゲットとするものだけを表示するコンポーネントを見つけます。ただし、正しいものを見つけたら残りの swizzle をファイルの削除によって解除することを忘れないでください。そうしないと、コンポーネントを多く保守することになります - テーマのソースコードを読み、賢く検索します
スウィズルする必要がありますか?
スウィズルは最終的に、Docusaurusの内部APIと対話する追加のReactコードを維持する必要があることを意味します。可能であれば、サイトをカスタマイズする際には以下の代替案を検討してください。
- CSSの使用 CSSのルールとセレクタは、多くの場合、適切なカスタマイズを実現するのに役立ちます。スタイリングとレイアウトの詳細を参照してください。
- 翻訳の使用 驚くかもしれませんが、翻訳は最終的には単にテキストラベルをカスタマイズする方法です。たとえば、サイトのデフォルトの言語が
en
の場合でも、yarn write-translations -l en
を実行して、出力されたcode.json
を編集できます。i18nチュートリアルの詳細を参照してください。
サイトを<Root>
でラップする
<Root>
コンポーネントは、テーマ<Layout>
より上のReactツリーの一番上にレンダリングされ、決してマウント解除されません。これは、ナビゲーション全体で再初期化されるべきではない状態fulなロジック(ユーザー認証ステータス、ショッピングカートの状態など)を追加するのに最適な場所です。
src/theme/Root.js
にファイルを作成して手動でスウィズルします。
import React from 'react';
// Default implementation, that you can customize
export default function Root({children}) {
return <>{children}</>;
}
React Context プロバイダをレンダリングするためにこのコンポーネントを使用します。