Next.js + Tailwind UI を使うとたった6時間で技術ブログのプロトタイプを作れる

@Panda_Program

Gatsby から Next.js に載せ替えた動機

本ブログを Next.js でリニューアルしました。 元々このブログは Gatsby で作っており、2019年3月にリリースしましたが(最初の投稿)、ついに Next.js に移行しました。移行のモチベーションはバージョン追従を避けたこと、デザインを一新したいこと、また記事が表示されないというバグが発生する事象があったことです。

まず Gatsby のバージョンアップについて。現在、Gatsby の最新バージョンが4系です。しかし、自分が使っていたテンプレートは3年前に1系から使い始めて、2年前に2系にバージョンアップしました。その後、自分は業務と個人開発で Next.js を使い始めたため、このブログでしか使っていなかった Gatsby の情報を追うのを止めて、記事だけ追加する運用をしていました。 その頃にはバージョンアップをするよりは Next.js で作り直そうと考えていました。

次に、デザインについてです。前のブログのデザインは Gatsby のスターターをそのまま使っていました。記事ページの幅や行間の余白や一部リンクの色や左カラムに表示するコンテンツを変えたものの、レイアウトやページネーションはスターターの実装のままでした。 このため、一から作り直して自分でサイトを作ったという感覚を得たかったという動機も原動力の一つです。 (画像はリニューアル前のトップページ)

リニューアル前のブログのトップページ

そして、記事が一覧に表示されないというバグが発生していたことも理由の一つです。 最新、または最新から1つ前の記事がトップページの一覧に表示されていませんでした。直リンクでアクセスすれば記事は表示されるのですが、せっかく書いた記事が人の目に触れないもどかしさを感じていたことも移行のきっかけになりました。

そして一番のきっかけは、今個人開発で作っているビールのレビューサイト(Beer Break)の休憩です。 2021年の9月末から作業を始めたため、このサイトの構想、Supabase の技術調査、仕様検討、実装を合わせるとすでに4ヶ月ほど経っています。

その間にもブログを作り直したいという気持ちは募っていたこと、サイトを作っている間に記事にしたい知見が溜まってきたこと、そして何よりユーザー登録から投稿の削除まで一通りサイトのリリースに必須の機能を実装できたことを考慮して、気分転換にブログを作り直そうと思い立ったのでした。

Next.js でブログを作る際に工夫したこと

さて、本題の Next.js ブログを作り直す際に工夫した点を紹介していきます。 ブログの開発は余暇の時間を使う個人開発です。このため、ここでいう工夫とは、開発の工数をできるだけ削減することです。そしてこの工夫は再現性があるため、例えば会社や個人で技術ブログを作る機会があればそのまま適用できるテクニックです。

先に結論を書くと、レイアウトを整えてダミーデータを入れ、Vercel にデプロイして一通り動くところまでたった4時間でできました。 なお、最終的にかかった時間は約48時間、工数にして約6人日です。そのうち記事ごとの OG 画像のデザインと自動生成プログラムの作成に1人日かかっているので、 ブログ作成にかけた工数は実質5人日です。(画像はOG画像のイメージ)

OG画像のサンプル

工数削減の前提. 慣れた技術を活用する

工数削減の工夫を説明する前に、工数削減の大前提は自分が慣れている技術を使うことです。 それにより学習コスト、つまりプロジェクトのセットアップ、公式ドキュメントの参照、チュートリアルの写経、デプロイ先の選定、ライブラリや関連ツール等エコシステムのチェックが不要になります。これは特に個人開発では重要な観点です。

今回、ブログを作り替えるにあたり新しく採用したツールは Vitest だけです。それ以外は自分がいつも使っている Next.js、Tailwind CSS、Vercel を選びました。これで技術調査と学習のコストはなくなりました。

関連記事: Next.js が好きな理由と2年間使い続けてきた感想

今回はサイトのリニューアルであるため、仕様策定に関するコストも大きくありません。 ページ数は4ページと多くなく、記事一覧ページ、各記事の個別ページ、以前作ったサイトを集めたポートフォリオと自分のプロフィールページだけです。しかも、今回は元になる Gatsby 製ブログがあるので、表示する内容は基本的に以前のものを踏襲するため新たに考えることはほぼゼロです。

Headless CMS を使うことも検討しました。しかし、以前からマークダウンファイルで記事を作成することに慣れていたこと、将来 MDX の対応をするかもしれないこと、frontmatter でメタ情報を柔軟に設定したいことから、今回は採用を見送りました。

仕様がほぼ固まっており、また慣れた技術を仕様することで上記の工数でを実現できたことは大きな前提です。 そして、以下で紹介する工数削減のキモは巨人の肩に乗ることです。ここでは、世界の人の過去の仕事の成果を借りてくることで、自分の仕事にレバレッジをかけることを指しています。

工数削減の工夫1. next-blog-starter を活用する

next-blog-starter

最初の工夫は Next.js の examples を活用したことです。

Next.js は GitHub レポジトリ上で様々なツールやライブラリと組み合わせた設定例を公開しています。この中の一つに blog-starter-typescript があります。これはマークダウンファイルを読み込み、SSG で記事ページをビルドするものです。サンプルのまま Vercel にデプロイしてもブログサイトとして動作します。

このスターターの嬉しいところは、md ファイルを読み込む記述とマークダウンをパースして html に変換するライブラリ、それをもとに記事ページを作るプログラムが同梱されていることです。 また、Frontmatter で記事のメタ情報を記述できます。

ブログサイトでは個別の記事ページのビルドに getStaticProps と getStaticPaths を活用します。blog-starter-typescript にはその記述も予め存在するので、フロントエンドでやるべきことは抽出するメタ情報を選択することと、画面を構築することです。つまり、Node.js のコードをほぼ書く必要なく、デザインと React の記述に集中可能になるのです。

工数削減の工夫2. Tailwind UI で UI を構築する

tailwindui

二つ目の工夫は、Tailwind UI を使うことです。 Tailwind UI は Tailwind CSS 公式の UI コンポーネント集です。HTML、React、Vue に対応しており、コピペですぐに使えます。一般的なコンポーネント集と異なり、これは有料で全てのパーツを購入すると$279です。

お金を払う必要はあるものの、コンポーネント自体を再販売しなければ商用でも利用可能であり、また購入した後のアップデートで新しいコンポーネントが追加されても追加料金を払わずに活用できます。

本音を書くと、これはあまり共有したくない情報でした。購入すれば誰でもハイクオリティなサイトを構築できるため、みんながこれを使ってサイトを構築すればデザインが差別化要因にならなくなるからです。

Tailwind UI はこれは人手が足りないスタートアップやデザイナーがいないチームで特に有用なツールです。実際、Supabasepapyrus といった新進気鋭のスタートアップのランディングページや管理画面を見て「このコンポーネント、Tailwind UI にあったな」と気づく回数が増えました。

Supabase に至っては Supabase UI という Tailwind UI を参考に、というかそのまま使っているようなコンポーネント集も作っています。ただし、これはライセンス違反ではありません。

supabase-ui

むしろ、Supabase UI はコンポーネントに渡す Props の定義や、Tailwind UI のコンポーネントの様々なバリエーション(例えば、モーダルでボタンが一つあるか二つあるか、アイコンは上に出すか左に出すか)を一つのコンポーネントにまとめる方法がとても参考になり重宝しています。

Tailwind UI でデザインフェーズが変わる

話を元に戻します。Tailwind UI を使うことでデザインフェーズでやるべきことが一変します。 今までは UI コンポーネント集を使ったとしても、ページのレイアウトに悩んだりそのコンポーネントの組み合わせ方に悩んでいました。

そしていざデザインに着手するとなると、デザインが素晴らしいサイトを眺めて参考にできるところを探し、Figma でデザインカンプを作成し、そのデザインカンプをもとに HTML と CSS を実装し、再利用できそうなところをコンポーネントに切り出し、実装起因でデザインとの差分が生じたら Figma を修正する(個人開発の場合は時には諦めることもある)というのがいつものフローでした。

しかし、Tailwind UI を使う場合、ヘッダーとフッターの一覧の中から好みのものを選択し、ブログやプロフィールなどページごとにコンテンツを出すための最適な UI を選ぶだけになります。 選んだ UI のコードをコピーし、ファイルにペーストしてコンポーネントとして扱います。データはダミーなので、Props で受け取れるようにプロパティ名を命名すれば準備完了です(画像は Tailwind UI のヘッダーの例)。

tailwind-uiのヘッダーの例

以上、1と2の工夫を実践した結果、たった 4時間でブログのプロトタイプが出来上がりました。 サイトの各ページと Twitter の 画像を見比べてもらうと、ほぼ同じ構成だということがわかると思います。4時間でここまでできたことは想定外でかなり驚きました。

工数削減の工夫3. @tailwindcss/typography でブログ記事のスタイリングをする

tailwind-css-typography

ここまででサイトの各ページのレイアウトが完成しました。次に工夫した点は Tailwind CSS の typography を活用したことです。このプラグインのすごいところは、proseというクラス名を一つ付与するだけでブログの文章のスタイリングが完了することです。

関連記事: Tailwind CSS入門 - フロントエンドで素晴らしい開発体験を得るために

これまで、コンテンツの幅、見出しや一文ごとのマージンや行間、ネストしたリストのインデント、引用や太字などのスタイリングは大変でした。細かいところに気を遣う上に、細部にこだわっていても全体としてバランスが整っていないと結局文章が読みにくくなるからです。それがproseというクラス名一つでとても読みやすいレイアウトになるのです。

prose はカスタマイズも簡単です。自分は今お読み頂いているこの文章のスタイルの調整に以下の CSS しか記述していません。ほとんど Heading と リンクの調整だけです。

markdown-styles.module.scss
.markdown {
  @apply prose prose-invert tracking-wide;

  // Headings
  @apply prose-headings:mb-4 prose-headings:border-b prose-headings:border-gray-700 prose-headings:pb-1 prose-headings:font-normal prose-headings:leading-snug prose-headings:text-gray-100;
  @apply prose-h2:mt-12 prose-h2:text-2xl;
  @apply prose-h3:mt-8 prose-h3:text-xl;
  @apply prose-h4:mt-8;

  // a
  @apply prose-a:text-blue-400 prose-a:no-underline prose-a:visited:text-indigo-400;

  // コード
  @apply prose-code:before:content-none prose-code:after:content-none;
  @apply prose-pre:rounded-tl-none prose-pre:bg-[#0d1117] prose-pre:p-2 prose-pre:shadow-lg;

  // strong
  @apply prose-strong:font-bold prose-strong:text-gray-50;

  // ul, li
  @apply marker:text-gray-400;
}

これを PostBody コンポーネントで呼び出しています。style['markdown'] が上記の CSS で、 contentはマークダウンから変換した HTML です。本文のコンポーネントはたったこれだけです。

PostBody.tsx
import { convertToReact } from '@/lib'
import style from '@/styles/markdown-styles.module.scss'

type Props = {
  initialContent: string
}

const PostBody: React.VFC<Props> = ({ content }) => {
  return (
    <div className="space-y-4">
      <div className={style['markdown']}>{convertToReact(content)}</div>

      <p className="text-gray-300">Happy Coding 🎉</p>
    </div>
  )
}

export default PostBody

ブログページに関する残りの作業は、シンタックスハイライトを hilight.js で適用したこと、a タグを next/link の Link コンポーネントに、img タグを next/image の Image コンポーネントに変換した程度です。

上記の Twitter のつぶやきではここまで8時間かかったと書いています。しかし、実はシンタックスハイライトまでであれば6時間で完成しています。今回のブログリニューアルを通じて、Next.js と Tailwind UI、Tailwind CSS のおかげでハイクオリティなプロトタイプを短時間で作成できることがわかりました。

終わりに

もちろんブログに必要なコンテンツは一覧とブログページだけではありません。同じタグやカテゴリの記事を表示したり、ページネーションを実装したりとやるべきことはたくさんあります。それでも「いい感じのサイトを思ったより楽に実装できる」とわかるだけでも大きな収穫です。

実際、たった数時間でプロトタイプが出来上がったため、これならリニューアルに時間はそれほどかからないだろうと自信を得ることができました。繰り返しになりますが作業開始からブログのデプロイまでにかかった時間は48時間、業務後に開発を進めたためかかった日数は10日でした。

このブログは Next.js で作成しているものの、工夫2と工夫3はバックエンドのフレームワークに関わらず活用できるテクニックです。皆さんの技術ブログ作成の参考になれば幸いです。

なお、リニューアル前のブログはこちらからご覧いただけます。

Happy Coding 🎉

パンダのイラスト
パンダ

記事が面白いと思ったらツイートやはてブをお願いします!皆さんの感想が執筆のモチベーションになります。最後まで読んでくれてありがとう。

  • Share on Hatena
  • Share on Twitter
  • Share on Line
  • Copy to clipboard