Docusaurusでクリスマス風のサイトを作ってみる
この記事は「株式会社メンバーズ Jamstack研究会主催 Advent Calendar
2023」の12日目の記事です。
はじめに
こんにちは。株式会社メンバーズ所属、フロントエンドエンジニアを名乗らせてもらっている長谷と申します。
今回は、Docusaurus(ドキュサウルス)というフレームワークを使ってサイトを作成し、ホスティングするまでの流れを記事にしてみました🦖
ちょっと長いですがお付き合いいただけますと幸いです。
主な登場人物(技術スタック)
Docusaurus:Meta社が開発した静的サイトジェネレーター。今回の記事の主役です。バージョンはv3.0.1(当記事執筆時点の最新版)を使用します。
Netlify:コンポーザブルWebプラットフォーム(公式サイトより)。Docusaurus公式ドキュメントの「Deployment」ページで、一番最初に導入方法が触れられていたからという安直な理由で採用しました。今回はホスティングに使用します。
01. インストール
公式ドキュメントの「Installation」ページではclassicテンプレートを導入することがおすすめされているので、素直におすすめを採用することにします。
npx create-docusaurus@latest doc-playground classic
プロジェクト名は「doc-playgounrd」にしてみました。安直とか言わない※このコマンドを打つ際にオプションを設定すればTypeScriptも使えますが、今回は使いません。
3分ほど待ったらインストールが終わります。
ちなみにインストールしたら以下のように主要コマンドを教えてくれます。親切。
[INFO] Inside that directory, you can run several commands:
`npm start`
Starts the development server.
`npm run build`
Bundles your website into static files for production.
`npm run serve`
Serves the built website locally.
`npm run deploy`
Publishes the website to GitHub pages.
We recommend that you begin by typing:
`cd doc-playground`
`npm start`
(あれっ……GitHub Pages使ったほうがよかった……?🙄)
とここで思いましたが、この記述に気づいたのはいろいろやっちゃったあとでもう引き返せなかったので、先に進みます。
コマンド「npm start」で開発用サーバーが立ち上がるということなので、素直に従って開発用サーバーを立ち上げてみます。
# ディレクトリ移動
cd doc-playground
# 開発環境立ち上げ
npm start
無事にサーバーが立ち上がると、デフォルト設定ではhttp://localhost:3000/からサイトを見ることができます。
なんかすでにいい感じです。テンプレートの魔力すごい。正直もうこれでいいかな…
02. ちょっと遊んでみる
もうこれでいいかなと思いつつも、ここで終わると記事としてはまったく面白味がないので、ちょっといじって遊んでみます。
せっかくなのでクリスマスっぽくしていきます。
02-01. 文言を変えてみる
デフォルトは英語なので日本語にしたいなと思います。
まず、サイト共通の文言についてはルートディレクトリにある「docusaurus.config.js」で設定できるので、以下のようにしてみました。
import {themes as prismThemes} from 'prism-react-renderer';
/** @type {import('@docusaurus/types').Config} */
const config = {
title: '今年もクリスマスがやってくる!',
tagline: '当サイトでクリスマス当日を楽しみに待ちましょう',
url: 'https://doc-playground-xmas.netlify.app/',
baseUrl: '/',
favicon: 'img/favicon.ico',
i18n: {
defaultLocale: 'ja',
locales: ['ja'],
},
presets: [
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: './sidebars.js',
},
blog: {
showReadingTime: true,
},
theme: {
customCss: './src/css/custom.css',
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
title: '今年もクリスマスがやってくる!',
logo: {
alt: '今年もクリスマスがやってくる!',
src: 'img/img_top.jpg',
},
items: [
{
type: 'docSidebar',
sidebarId: 'tutorialSidebar',
position: 'left',
label: 'クリスマスについて',
},
{ to: '/blog', label: 'アドベントカレンダー', position: 'left' },
{
href: 'https://github.com/facebook/docusaurus',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
style: 'dark',
copyright: `Copyright © ${new Date().getFullYear()} Doc Playgound, Inc. Built with Docusaurus.`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
}),
};
export default config;
ここまでの結果▼
02-02. コンポーネントをいじってみる
コンポーネントは./src/components/に格納されているので、それをいじります。(このclassicテンプレートにおいては)CSS in JSはCSS Modulesが採用されています。
というわけで、以下のようにちくちくといじってみました。
./src/components/HomepageFeatures/index.js▼
import clsx from 'clsx';
import Heading from '@theme/Heading';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'Google サンタを追いかけよう',
href: 'https://santatracker.google.com/intl/ja/',
imgSrc: require('@site/static/img/img_features_01.jpg').default,
description: (
<>
サンタさんの妖精たちと一緒にサンタ村を探検したり、ゲームをしたり、クリスマスについて学ぼう!
</>
),
},
{
title: 'クリスマスツリーを飾ろう',
href: 'https://www.amazon.co.jp/s?k=%E3%82%AF%E3%83%AA%E3%82%B9%E3%83%9E%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=27WECPA72RKJU&sprefix=%E3%82%AF%E3%83%AA%E3%82%B9%E3%83%9E%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC+%E9%80%9A%E8%B2%A9%2Caps%2C265&ref=nb_sb_noss_2',
imgSrc: require('@site/static/img/img_features_02.jpg').default,
description: <>クリスマスツリーを飾って気分をあげよう!</>,
},
{
title: '大切な人にプレゼントを贈ろう',
href: 'https://www.amazon.co.jp/b?ie=UTF8&node=10358336051&pd_rd_w=N86T3&content-id=amzn1.sym.fc3588ca-d765-46aa-b326-a95cd476e3ee&pf_rd_p=fc3588ca-d765-46aa-b326-a95cd476e3ee&pf_rd_r=C5WJZ9FS4EGYRRDKT2PK&pd_rd_wg=pZMOv&pd_rd_r=814a4a9c-a117-4e57-93ad-010343805994',
imgSrc: require('@site/static/img/img_features_03.jpg').default,
description: <>大切なあの人へのプレゼントを選ぼう!</>,
},
];
function Feature({ href, imgSrc, title, description }) {
return (
<div className={clsx('col col--4')}>
<a
className={styles.featureLink}
href={href}
target='_blank'
rel='noopener noreferrer'
>
<p className='text--center'>
<img src={imgSrc} className={styles.featureImg} role='img' />
</p>
<div className='text--center padding-horiz--md'>
<Heading as='h3'>{title} →</Heading>
<p>{description}</p>
</div>
</a>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className='container'>
<div className='row'>
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}
./src/components/HomepageFeatures/styles.module.css▼
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureLink {
display: block;
text-decoration: none;
}
.featureLink:hover {
text-decoration: none;
}
.featureImg {
height: 200px;
width: 200px;
transition: 0.3s ease transform;
}
.featureLink:hover .featureImg {
transform: scale(1.1);
}
ついでにガワのほうもいじります。ガワは./src/pages/に格納されています。(だいぶ手抜き実装ですみません)
./src/pages/index.js▼
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import Heading from '@theme/Heading';
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<Heading as="h1" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/intro">
5分でわかるクリスマス ⏱️
</Link>
</div>
</div>
</header>
);
}
export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`${siteConfig.title}`}
description='クリスマス当日を楽しみに待つためのサイトです。'
>
<HomepageHeader />
<main>
<Heading as='h2' className={styles.heading02}>
おすすめリンク
</Heading>
<HomepageFeatures />
<p className={styles.materialCopyrightText}>
ねこアイコン素材:
<a
href='https://mozneko.boo.jp/'
target='_blank'
rel='noopener noreferrer'
>
もずねこ
</a>
様
</p>
</main>
</Layout>
);
}
./src/pages/index.module.css▼
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}
.heading02 {
text-align: center;
margin-top: 40px;
}
.materialCopyrightText {
text-align: center;
}
ここまでの結果▼
03. ホスティングしてみる
遊んで満足したところでホスティングをします(本当はトップ以外も見た目いじったりしたかったのですが、また別の機会に……)。
ここでようやくNetlifyくんの出番です。
ログインしたら、「Add new site」ボタンを押して「Import an existing project」を選択し、設定していきます。
今回はGitHubにソースを入れているので、「Deploy with GitHub」ボタンを押します。
対象のリポジトリを選択します。
「Build command」がnpm run build、
「Publish directory」がbuildになっているのを確認したら
「Deploy doc-playground」ボタンを押していざデプロイ!
04. 完成品
こうして出来上がったサイトがこちらになります。
https://doc-playground-xmas.netlify.app/
(ファビコンから手抜き実装がばれます)
(ダークモードでみるとさらに手抜き実装がばれます)
(「クリスマスについて」と「アドベントカレンダー」は整備しきれませんでした…)
GitHubにもソースを置いているので気になる方はご覧ください!
おわりに
今回はDocusaurusでクリスマス風サイトを作ってみました。
初めて使ってみた所感としては、
ディレクトリ構成がシンプル
classicテンプレートが拡張しやすい
classicテンプレートをベースに自作テーマが作りやすそう
全体的に学習コストが少なく扱いやすい印象
といった感じでした!
Netlifyは今まで何度か使った経験がありますが、やっぱりデプロイまでのステップが簡単・爆速で使いやすいですね。
何かしら参考になる部分がありましたら幸いです。
長くなってしまいましたが、ここまでお付き合いいただきありがとうございました!