- 1. 参考書籍
- 2. 全体設計
- 1. SSGのみで構成したい
- 2. 画像データは専用サーバに移行
- 3. 既存記事データとMarkdownデータの棲み分け
- 4. 全体のフォルダ構成
- 3. 使用ライブラリの選定
- 1. 使用ライブラリ
- 1. フレームワーク
- 2. スタイリング
- 3. 開発環境
- 4. 記事ファイル変換
- 5. 記事コンテンツ
- 4. 全体のレイアウトを作成する
- 1. Next.jsプロジェクトの作成
- 2. ESLint、Prettierの設定
- 3. スタイリングの初期設定
- 1. Emotionのインストール
- 2. コンポーネントへのスタイル適用
- 3. グローバルスタイルの適用
- 4. テーマの適用
- 4. Storybookの導入
- 5. レイアウト実装
- 1. 全体のレイアウト
- 2. ヘッダー、フッター
- 3. タイトルエリア
- 4. サイドバー
- 5. Netlifyサーバへのデプロイ
- 6. おわりに

マイケル
みなさんこんにちは!
マイケルです!

エレキベア
こんにちクマ〜〜

マイケル
この度、WordPress製だった当ブログをNext.jsで作り直しました!
そのため三記事ほどに分けて、実際に開発した内容を紹介していきます。

【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
2024-01-01

【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
2023-12-31

【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
2023-12-31

【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
2023-12-31

【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜
2023-12-31

エレキベア
おめでたいクマ〜〜〜

マイケル
今回は第一回ということで「全体設計、環境構築」編 になります!
コードについても公開できる範囲でGitHubに上げているので、同じようにNext.jsに移行したと考えている方はご参考ください!
GitHub - nextjs-elekibear-blog-scripts

エレキベア
中々ボリュームがあるクマね・・・
参考書籍

マイケル
Next.jsの学習をするにあたり、下記書籍を参考にさせていただきました!

TypeScriptとReact/Next.jsでつくる実践Webアプリケーション

マイケル
前半のJavaScriptの歴史〜React、Next.jsの解説が非常に分かりやすかったです!
Next.js12使用でPageRouterでの記載にはなっていますが、本格的にアプリ開発したい方にはおすすめです!

エレキベア
最近のWeb技術をキャッチアップしたい方にはおすすめクマね
全体設計

マイケル
まずはWordPressブログを移行するにあたり、
どのような設計にしたか?について触れていきます。
SSGのみで構成したい

マイケル
ベースとなる考えとして、DBサーバは使用せずにSSGのみで構成したい というものがあったため、フレームワークは Next.jsを使用 することにしました。
SSGは 静的サイトジェネレータ の略で、 デプロイする前に事前にデータフェッチして静的サイトを生成しておく手法 になります。

▲静的サイトジェネレータのイメージ

マイケル
静的サイト化することで、
・閲覧時のサーバ通信が発生しないためレスポンスが高速になる
といった大きなメリットがあります。
他の主要なレンダリング手法としては下記のようなものがあります。
フロントエンドのレンダリング手法
名称 | 概要 | 特徴 |
---|---|---|
SSG 静的サイトジェネレータ | 事前にデータを取得して静的ファイルを生成する。 | 初期描画、レスポンスが高速だが、データのリアルタイム性が求められるコンテンツには適さない。 |
CSR クライアントサイドレンダリング | ブラウザで初期描画した後に非同期でデータ取得して描画する。 | 初期描画が遅いが、リアルタイム性が重要なページに適している。 |
SSR サーバサイドレンダリング | ページへのアクセス毎にサーバ側で描画してクライアントへ渡す。 | 常に最新のデータを扱うことが出来るが、レスポンスが遅い。 |
ISR インクリメンタル静的再生成 | 事前にページを生成しつつ。アクセスに応じて再度ページを生成し直す。(SSGの応用) | SSGとSSRの中間のような特徴がある。 |

エレキベア
なるほどクマ
データをリアルタイムにやり取りしない限りはなるべくSSGにするのがよさそうくまね

マイケル
当サイト含む個人ブログに関しては更新頻度が頻繁にあるわけではなくリアルタイム性も求められないため、SSGの恩恵をフルに受けられるというわけです。
今回開発するページは下記二つのため、どちらもSSGで対応できそうです。
開発するページの種類
URLパス | ページ |
---|---|
/ | 記事一覧ページ |
/post/[slug] | 記事ページ |

マイケル
また、静的サイトであれば無料で公開できるホスティングサービスもあるため
サーバ費用が抑えられるのも大きなメリットです。
今回は、2024/1現在で商用利用も可能な Netlify を使用することにしました。

エレキベア
サーバ費用も実質無料にできるということクマか・・・
恐ろしいクマ・・・
画像データは専用サーバに移行

マイケル
NetlifyへのデプロイはGitHubリポジトリと連携するのを想定しているのですが、
画像ファイルについては容量が大きいため、その内リポジトリで管理しきれなくなる可能性があるのではないか?という懸念がありました。

エレキベア
確かに現状で200記事以上あるクマからね・・・

マイケル
そのため、画像ファイル類はアプリケーションとは別のサーバで管理することにしました。
そちらもNetlifyで別途サーバを立ててデプロイしています。
デプロイするサーバ
種類 | ドメイン |
---|---|
アプリケーション | elekibear.com(wp-next-eleikibear.netlify.app) |
画像ファイル類 | wp-next-elekibear-content.netlify.app |

エレキベア
Netlifyフル活用クマ〜〜〜

マイケル
まあNetlifyでも耐えきれない時が来るかもしれないし、
また後々サーバ移行する自体になった時にも分けておいた方が対応しやすそうだね
Netlifyサーバでの運用では、Bandwidth(帯域幅)の領域が100GBギリギリとなってしまったため、 現在はVPSサーバを用意してそちらに格納する運用にしています。
既存記事データとMarkdownデータの棲み分け

マイケル
そして記事データの管理方法についてですが、既存のWordPressデータに関しては必要なデータをCSV(+記事テキスト)として出力 して参照するようにしました。
DBサーバは完全に使用しない方向で、またローカルでもデータベース管理するほどではないと判断したためです。

マイケル
そしてやはり今後の記事執筆に関してはMarkdownを使用したいため
下記のような形で既存データと今後のデータで分けて管理するようにしました。

▲既存のWordPressデータはエクスポートして表示し、今後はMarkdownで執筆できるようにする

エレキベア
執筆作業はその方が絶対に効率いいクマね
全体のフォルダ構成

マイケル
以上を踏まえて、下記のようなフォルダ構成で管理することにしました。
dataフォルダ内にマスタデータ(CSV)、記事データ(Text、Markdown)を格納しています。
全体のフォルダ構成
フォルダ名 | 内容 |
---|---|
data | マスタデータ(CSV)、記事ファイル(Text or Markdown) |
public | 画像や外部スクリプトファイル等 |
src | スクリプト |
tools | 開発や記事執筆に使用するツール群 |
src配下のフォルダ構成
フォルダ名 | 内容 |
---|---|
api | データ操作関連の処理(CSV、Markdown) |
common | スクリプト全体の共通処理 |
components | UIコンポーネント群 |
pages | ページ起点 |
parser | データ変換関連の処理(Markdown) |
settings | 設定ファイル |
style | スクリプト全体の共通style群 |
theme | Emotionスタイルテーマ |
types | 型定義ファイル |

エレキベア
これならいい感じに整理できそうクマね
使用ライブラリの選定
使用ライブラリ

マイケル
使用した主なライブラリについては下記になります。
該当箇所 | ライブラリ |
---|---|
フレームワーク | Next.js (※PageRouterを使用) |
スタイリング | Emotion (※CSSPropsを使用) |
開発環境 | ESLint、Prettier、Storybook |
記事ファイル変換 | テキスト記事:cheerio Markdown記事:react-markdown、gray-matter、rehype-raw |
記事コンテンツ | Prism.js、MathJax、Codepen、X |
フレームワーク

マイケル
フレームワークは大定番のNext.js!
理由は先ほど述べた通り、SSGで構成したいかつReact実装を経験したかったためです。


エレキベア
今は定番になりつつあるクマから、情報量も多くて作りやすそうクマね

マイケル
ただ、今回の開発ではNext.js 13.4から推奨となったAppRouterは使用せず、
従来のPageRouterを使用する方針で開発を進めました。
Next.js自体触るのが初めてだったため、下記理由によりまずは開発スピード優先で進めることにしたためです。
- 従来の形式と設計が大きく変わったため、未対応のライブラリも多い
- 現時点でPageRouterで実装した情報の方が多い

エレキベア
まあPageRouterも一度は触っておきたいクマね

マイケル
とはいえAppRouterは今後スタンダードになっていくと思われるため、
その内Next.jsのアップデートと合わせて移行対応も行ってみようかと思っています。
スタイリング

マイケル
スタイリング手法としては、CSS-in-JS である Emotion を使用することにしました。
選定した理由としては下記になります。
- CSS-in-JSの使用により、コンポーネント単位のファイルをまとめたい
- EmotionのCSSPropを使用することで、素のCSSに近い形で実装したい
- グローバルCSS、テーマ機能、パラメータによる動的指定など、必要な機能が揃っている

マイケル
同じCSS-in-JSであるstyled-componentでなくEmotionを選んだ理由としては二つ目の「CSSPropを使用したい」という理由が大きいです。
JSファイル内に実装しつつもCSS、JSXが素の状態に近いため、後々ライブラリを移行する必要が出てきても棄てやすいと判断したためです。


エレキベア
棄てやすさは大事クマ・・・

マイケル
現にAppRouterに対応していないようなので、もうしばし様子を見て対応されないようであれば移行を検討する可能性も高いですね・・・

マイケル
ちなみに同様の理由でtailwindCSSやBootStrapといったCSSライブラリも一切使用せずEmotionのCSSPropによるCSS実装のみで完結させています。
tailwindに関しては複雑な画面を組むとごちゃごちゃになるし、ライブラリへの依存も強い気がしますね・・・

エレキベア
確かに便利クマが、一度使うと抜けられない危険はありそうクマね
開発環境

マイケル
開発環境としては、コード整形ツールとしてESLintとPrettier、
UIカタログツールとしてStorybookを導入しました。

エレキベア
ESLint、Prettierは定番クマね
Storybookは何に使うクマ?

マイケル
StorybookはUIコンポーネント単位でカタログ表示・管理ができるツールなんだ。
コンポーネントからボトムアップで開発したり、バリエーションを確認するのに役立ちます。


エレキベア
なるほどクマ
これはReactと相性がよさそうクマね
記事ファイル変換

マイケル
記事データを操作、変換するライブラリとして、
既存のテキストファイルはcheerio、
MarkdownファイルはReactMarkdownとgray-matterを使用することにしました。

エレキベア
変換処理もいろいろカスタマイズが必要そうクマね

マイケル
このあたりは第二回、第三回で使用例を解説するため今回は省略します。
記事コンテンツ

マイケル
最後に、記事コンテンツ内で使用しているライブラリとして下記があります。
ライブラリ名 | 用途 |
---|---|
Prism.js | コード表示 |
MathJax | 数式表示 |
Codepen | コード結果表示 |
X | Xポスト表示 |

エレキベア
いつもお世話になってる機能クマね

マイケル
この辺りは外部スクリプトとして読み込むようにしています。
記事の内容に適用する関係でNext/Scriptではなく記事表示時に動的に読み込むよう実装したのですが、この辺りも次回以降解説させてください。
全体のレイアウトを作成する

マイケル
それでは以上のライブラリを使用しながら、下記のような簡単な2カラムレイアウトを作ってみます。

▲よくある2カラムレイアウト

▲一応レスポンシブ

エレキベア
このブログサイトの構成に近いクマね

マイケル
環境構築から開発のイメージまでざっくり知っていただければと思います。
今回作るサンプルはGitHubにも上げていますので、よければご参照ください。
GitHub - nextjs-emotion-layout-sample
Next.jsプロジェクトの作成

マイケル
まずはcreate-next-appを実行してNext.jsのプロジェクトを作成します。
オプションは「use `src/` directory」以外は No を選択して、AppRouterではなくPageRouterを使用するようにします。

エレキベア
ボイラーテンプレートがあるのはありがたいクマね

マイケル
作成後に プロジェクトフォルダ直下でnpm run devを実行、localhost:3000にアクセスするとサンプル画面が表示されるはずです。

▲サンプル画面が表示される

エレキベア
簡単クマ〜〜〜〜
ESLint、Prettierの設定

マイケル
次にESLint、Prettierを導入します。
React、Next.js用も含めて、下記コマンドでインストールします。

エレキベア
たくさんあるクマ・・・

マイケル
そして設定ファイルとして .eslintrc.json、.prettierrc.json を作成します。
今回は下記のように設定しました。

エレキベア
この辺はお好みに合わせて変更するクマね

マイケル
最後にpackage.jsonを下記のように設定します。
これによりnpm run check、npm run formatでコードのチェック・整形を行うことができます。

エレキベア
これでコード整形は完璧クマ〜〜〜
スタイリングの初期設定

マイケル
次にEmotionを導入していきます。
こちらは設定が少々手間がかかる印象でした。
Emotionのインストール

マイケル
今回はCSSPorpを使用するため、@emotion/reactのみインストールします。

マイケル
インストールしたらnext.config.js、tsconfig.jsのそれぞれの設定ファイルにEmotionを有効にするよう設定します。

マイケル
あとはESLintの設定でエラーが出ないよう設定すれば完了です!

エレキベア
中々面倒くさいクマ・・・
コンポーネントへのスタイル適用

マイケル
基本的な使い方としては、下記のようにコンポーネント内でCSSを定義・適用します。


エレキベア
分かりやすいクマ〜〜〜
グローバルスタイルの適用

マイケル
グローバルにCSSを使用したい場合には、Globalタグにスタイルを設定して囲むことで適用することができます。

エレキベア
従来のCSSのように使えるのクマね
テーマの適用

マイケル
グローバルCSS以外にも、共通のテーマを持たせる方法もあります。
例えば下記のようなカラーのテーマを用意してみます。

マイケル
これをThemeProviderタグに設定して囲むことで適用することができます。
使い方はCSS指定の際にthemeを引数として受け取るようにするだけです。

▲テーマに設定したカラーが表示される
Storybookの導入

マイケル
最後にStorybookを導入します。
下記コマンドを実行すると、ライブラリとサンプルコードが格納されます。
▲コマンドも追加される

マイケル
インストール後に npm run storybook を実行すると、localhost:6006 でStorybookの画面にアクセスできるようになっているはずです。

▲Storybookの画面が開く

エレキベア
この画面で作成したコンポーネントを確認できるようになるクマね

マイケル
Storybookには、XXX.stories.tsx の拡張子でファイルを作成することで追加できます。
下記のようにStoryFn型で定義したコンポーネントをbindすることで表示します。

マイケル
通常はこれだけで表示されるようになるのですが、Emotionを使用している場合にはスタイル適用の追加対応が必要になります。
下記二点について追加で対応します。
- preview.ts の修正
- preview.ts -> preview.tsx にリネーム
- グローバルスタイル、テーマの適用を追加する
▲グローバルスタイル、テーマの適用
- Storybook側のBabel設定
- babel-preset-css-prop をインストールして .storybook/main.ts に設定する
- 参考:Qiita - Next.jsにemotionを導入する時にstorybookにスタイルが当たってくれない問題
▲EmotionのBabel設定を追加

マイケル
以上の設定でEmotionのスタイルが適用されているはずです!


エレキベア
やったクマ〜〜〜〜
レイアウト実装

マイケル
環境が整ったところで、試しに簡単なレイアウトを作成してみます。
当サイトでもベースとなっている、ヘッダー、タイトルエリア、メインエリア、サイドバー、フッターの五つのエリアで構成されている画面になります。

全体のレイアウト

マイケル
全体のレイアウトの指定について、
src/pages/_app.tsx
src/pages/index.tsx
はそれぞれ下記のようにしています。
▲Headタグも含めて_app.tsxに定義する
▲ページからはLayoutコンポーネントを表示するようにする

エレキベア
ページ側ではLayoutコンポーネントを表示しているだけクマね

マイケル
Layoutコンポーネントに渡しているCenterTextコンポーネントについては、
下記のように中央にテキスト表示だけのコンポーネントになっています。
このようにUIパーツごとに分けて開発できるのがReactの強みですね!
▲中央にテキストを表示するだけのコンポーネント

マイケル
Layoutコンポーネント内では、ヘッダーやフッターといったコンポーネントをそれぞれ表示するようにしています。
xl、lgといった指定は、メディアクエリの共通ブレイクポイントとしてEmotionで指定できるようにしました。
▲Layoutコンポーネント
▲メディアクエリのブレイクポイント対応

エレキベア
ブレイクポイントを指定できるようにしておけば
レスポンシブ対応しやすそうクマね

マイケル
ヘッダーやサイドバー等についてはそれぞれ以下のようになっています。
実装内容について特に特殊なことはしていないので、解説は省略します。
ヘッダー、フッター
タイトルエリア
サイドバー

マイケル
以上で2カラムのレイアウトが実装できているはずです。
このようにUIコンポーネント単位で分けながら開発を進めます。

エレキベア
部品ごとに分けるから管理や再利用がしやすそうクマね
Netlifyサーバへのデプロイ

マイケル
最後に、今回作ったプロジェクトをNetlifyにデプロイしてみます。
アカウント登録後、「Add new site」ボタンからプロジェクトを追加できます。
今回はGitHubリポジトリをそのままデプロイするため「Import an existing project」を選択します。


マイケル
デプロイするサービスとしてGitHub、デプロイしたいリポジトリを選択します。
設定画面にてデプロイボタンを押下すればリポジトリと紐づけられ、以降は対象のブランチに変更がある度にデプロイされます。

▲デプロイするリポジトリを選択

▲設定画面 - Build command に設定したコマンドがビルド時に実行される

エレキベア
簡単クマ〜〜〜〜

マイケル
デプロイが完了次第、割り振られたURLを開くとブラウザ上で確認できるようになっているはずです。

▲デプロイ完了後、URLを開くとデプロイされていることが確認できる

▲正常に表示することができた

エレキベア
これでプロジェクトのテンプレートからデプロイ環境まで一通り整ったクマね

マイケル
Netlifyでは、今回紹介したGitHubリポジトリのデプロイ以外でも
ドラッグ&ドロップ、コマンドによるデプロイ方法もサポートしています。
この辺りは好みや用途に合わせて選択してください。
コマンドによるデプロイ方法

エレキベア
GitHubで管理しない資産はコマンドを使用する方が良さそうクマね
おわりに

マイケル
というわけで今回はNext.jsプロジェクトの設計について触れていきました!
どうだったかな??

エレキベア
ライブラリの組み合わせ、環境構築は中々面倒だったクマ
でも一度整えてしまえば快適な開発環境になるクマね

マイケル
最初は面倒くさいけど、やっぱりコーディングできる状態まで来ると楽しいね!
あとはWordPressのデータをどう移行するかすごく悩んだけど、とりあえずは今回の構成でどうにかなりそうです。

マイケル
次回は実際にWordPressデータを移行・表示する流れを紹介していきます!
アデューー!!

エレキベア
クマ〜〜〜〜
【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜 〜完〜

【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
2024-01-01

【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
2023-12-31

【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
2023-12-31

【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜
2023-12-31