Docusaurus

コラボレーションツール

Docusaurus

概要

Docusaurusは、Metaが開発した強力な静的サイトジェネレーターで、特にドキュメントサイトの構築に特化しています。Reactベースで構築され、MarkdownとMDXのサポート、バージョン管理、多言語対応、強力な検索機能など、技術ドキュメントに必要な機能を標準装備しています。開発者が美しく、メンテナンスしやすいドキュメントサイトを素早く構築できるよう設計されています。

詳細

Docusaurusは、技術ドキュメント、プロダクトドキュメント、ブログを統合したサイトを簡単に構築できるツールです。Reactコンポーネントとしてカスタマイズ可能で、MDXを使用することで、Markdownの中にReactコンポーネントを埋め込むことができます。ビルトインのバージョニング機能により、複数バージョンのドキュメントを同時に管理でき、Algoliaとの統合により高速な検索機能を提供します。プラグインアーキテクチャにより、機能を柔軟に拡張できます。

主な機能

  • Markdown/MDXサポート: MarkdownとReactコンポーネントの統合
  • バージョニング: 複数バージョンのドキュメント管理
  • 国際化(i18n): 多言語ドキュメントのネイティブサポート
  • 検索機能: Algolia DocSearchとの統合
  • プラグインシステム: 柔軟な機能拡張
  • テーマカスタマイズ: ブランディングに合わせたデザイン変更
  • ブログ機能: ドキュメントと統合されたブログ
  • 自動デプロイ: GitHub Pages、Netlify、Vercelとの統合

プラグインAPI概要

プラグイン構造

module.exports = function(context, options) {
  return {
    name: 'my-plugin',
    async loadContent() {
      // コンテンツの読み込み
    },
    async contentLoaded({content, actions}) {
      // コンテンツ処理後のアクション
    },
    configureWebpack(config, isServer, utils) {
      // Webpack設定のカスタマイズ
    }
  };
};

ライフサイクルフック

// 主要なライフサイクルメソッド
{
  loadContent(): Promise<any>
  contentLoaded({content, actions}): Promise<void>
  postBuild(props): Promise<void>
  configureWebpack(config, isServer, utils): object
  getThemePath(): string
  getClientModules(): string[]
  injectHtmlTags({content}): object
}

メリット・デメリット

メリット

  • Metaによる開発とサポート
  • ドキュメント特化の豊富な機能
  • 優れた開発者体験
  • 高速なビルドとパフォーマンス
  • SEO最適化済み
  • アクティブなコミュニティ
  • 豊富なプラグインエコシステム

デメリット

  • Reactの知識が必要(高度なカスタマイズ時)
  • 静的サイトのみ(動的機能は限定的)
  • ビルド時間が長くなる可能性(大規模サイト)
  • プラグイン開発が複雑
  • APIドキュメント専用機能は手動実装が必要
  • デザインのカスタマイズに制限

実践的な例

1. 基本的なDocusaurusプロジェクトのセットアップ

# プロジェクトの作成
npx create-docusaurus@latest my-docs classic

# 依存関係のインストール
cd my-docs
npm install

# 開発サーバーの起動
npm start

# プロダクションビルド
npm run build

# ビルドしたサイトのプレビュー
npm run serve

2. docusaurus.config.js の設定

// @ts-check
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');

/** @type {import('@docusaurus/types').Config} */
const config = {
  title: 'My Documentation',
  tagline: 'Technical documentation made easy',
  url: 'https://mydocs.example.com',
  baseUrl: '/',
  onBrokenLinks: 'throw',
  onBrokenMarkdownLinks: 'warn',
  favicon: 'img/favicon.ico',
  organizationName: 'myorg',
  projectName: 'mydocs',
  
  i18n: {
    defaultLocale: 'ja',
    locales: ['ja', 'en'],
    localeConfigs: {
      ja: {
        label: '日本語',
        direction: 'ltr',
      },
      en: {
        label: 'English',
        direction: 'ltr',
      },
    },
  },

  presets: [
    [
      'classic',
      /** @type {import('@docusaurus/preset-classic').Options} */
      ({
        docs: {
          sidebarPath: require.resolve('./sidebars.js'),
          editUrl: 'https://github.com/myorg/mydocs/tree/main/',
          remarkPlugins: [],
          rehypePlugins: [],
          showLastUpdateAuthor: true,
          showLastUpdateTime: true,
        },
        blog: {
          showReadingTime: true,
          editUrl: 'https://github.com/myorg/mydocs/tree/main/',
        },
        theme: {
          customCss: require.resolve('./src/css/custom.css'),
        },
      }),
    ],
  ],

  themeConfig:
    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    ({
      navbar: {
        title: 'My Docs',
        logo: {
          alt: 'My Docs Logo',
          src: 'img/logo.svg',
        },
        items: [
          {
            type: 'doc',
            docId: 'intro',
            position: 'left',
            label: 'ドキュメント',
          },
          {to: '/blog', label: 'ブログ', position: 'left'},
          {
            href: 'https://github.com/myorg/mydocs',
            label: 'GitHub',
            position: 'right',
          },
          {
            type: 'localeDropdown',
            position: 'right',
          },
        ],
      },
      footer: {
        style: 'dark',
        links: [
          {
            title: 'ドキュメント',
            items: [
              {
                label: 'はじめに',
                to: '/docs/intro',
              },
              {
                label: 'APIリファレンス',
                to: '/docs/api',
              },
            ],
          },
        ],
        copyright: `Copyright © ${new Date().getFullYear()} My Organization.`,
      },
      prism: {
        theme: lightCodeTheme,
        darkTheme: darkCodeTheme,
        additionalLanguages: ['rust', 'ruby', 'php'],
      },
      algolia: {
        appId: 'YOUR_APP_ID',
        apiKey: 'YOUR_SEARCH_API_KEY',
        indexName: 'mydocs',
        contextualSearch: true,
      },
    }),
};

module.exports = config;

3. カスタムプラグインの作成

// plugins/custom-plugin.js
module.exports = function (context, options) {
  return {
    name: 'custom-documentation-plugin',
    
    async loadContent() {
      // 外部APIからドキュメントを読み込む
      const apiDocs = await fetchAPIDocumentation();
      return apiDocs;
    },
    
    async contentLoaded({content, actions}) {
      const {createData, addRoute} = actions;
      
      // データファイルを作成
      const apiDocsPath = await createData(
        'api-docs.json',
        JSON.stringify(content)
      );
      
      // 新しいルートを追加
      addRoute({
        path: '/api-reference',
        component: '@site/src/components/APIReference',
        props: {
          apiDocsPath,
        },
        exact: true,
      });
    },
    
    configureWebpack(config, isServer, utils) {
      return {
        module: {
          rules: [
            {
              test: /\.yaml$/,
              use: 'yaml-loader',
            },
          ],
        },
        resolve: {
          alias: {
            '@api': path.resolve(__dirname, '../src/api'),
          },
        },
      };
    },
    
    getThemePath() {
      return path.resolve(__dirname, './theme');
    },
    
    injectHtmlTags({content}) {
      return {
        headTags: [
          {
            tagName: 'link',
            attributes: {
              rel: 'preconnect',
              href: 'https://fonts.googleapis.com',
            },
          },
        ],
        preBodyTags: [],
        postBodyTags: [],
      };
    },
  };
};

// 使用例: docusaurus.config.js
module.exports = {
  plugins: [
    ['./plugins/custom-plugin', {
      apiEndpoint: 'https://api.example.com/docs',
    }],
  ],
};

4. MDXコンポーネントとカスタムページ

// src/components/APIEndpoint.js
import React from 'react';
import CodeBlock from '@theme/CodeBlock';

export default function APIEndpoint({method, path, description, example}) {
  const methodColors = {
    GET: '#61affe',
    POST: '#49cc90',
    PUT: '#fca130',
    DELETE: '#f93e3e',
  };
  
  return (
    <div className="api-endpoint">
      <div className="api-header">
        <span 
          className="method" 
          style={{backgroundColor: methodColors[method]}}
        >
          {method}
        </span>
        <code className="path">{path}</code>
      </div>
      <p className="description">{description}</p>
      {example && (
        <div className="example">
          <h4></h4>
          <CodeBlock language="json">{example}</CodeBlock>
        </div>
      )}
    </div>
  );
}

// ドキュメントでの使用例(.mdx ファイル)
/*
---
title: API リファレンス
---

import APIEndpoint from '@site/src/components/APIEndpoint';

# API リファレンス

## ユーザー管理

<APIEndpoint
  method="GET"
  path="/api/users"
  description="すべてのユーザーを取得"
  example={`{
  "users": [
    {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]"
    }
  ]
}`}
/>

<APIEndpoint
  method="POST"
  path="/api/users"
  description="新しいユーザーを作成"
  example={`{
  "name": "Jane Doe",
  "email": "[email protected]"
}`}
/>
*/

5. バージョニングとローカライゼーション

# 新しいバージョンを作成
npm run docusaurus docs:version 1.0.0

# ディレクトリ構造
# versioned_docs/
#   version-1.0.0/
#     intro.md
#     api/
#       overview.md
# versions.json

# 翻訳ファイルの初期化
npm run write-translations -- --locale ja

# i18n ディレクトリ構造
# i18n/
#   ja/
#     docusaurus-plugin-content-docs/
#       current/
#         intro.md
#       version-1.0.0/
#         intro.md
#     docusaurus-theme-classic/
#       navbar.json
#       footer.json

6. GitHub Actionsでの自動デプロイ

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Deploy to GitHub Pages
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: npm

      - name: Install dependencies
        run: npm ci
        
      - name: Build website
        run: npm run build
        env:
          NODE_ENV: production

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./build
          user_name: github-actions[bot]
          user_email: 41898282+github-actions[bot]@users.noreply.github.com

参考リンク