Next.jsでブログをつくってみる

Technical

記念すべき一投目はこのブログを作るところから。

Next.jsで作ってみるか

最近はReactばかり触っているのであまり深く考えずにNext.jsを選定。

今回はじめて作るのでVercel公式のNext.js Blog Starter Kits & Templatesをボイラープレートにして作っていきます。

このサンプルに対応するGitHubリポジトリはnext.js/examples/blog-starterです。

コードをざっと確認したところReact 19ベースでApp Router使用, TypeScript。Tailwind v3で、コンポーネントのスタイル指定はCSS Modulesを併用しているっぽいです。

npx create-next-app --example blog-starter blog-starter-app

PrettierとESLintを導入する

サンプルのファイルにはフォーマッタやLinterが設定されていないので、設定します。

ESLintの設定に関してはConfiguration: ESLint | Next.js参照。

npm i -D eslint eslint-config-next eslint-config-prettier

Prettierとあわせてimport行を並べ替えるプラグインと、Tailwind公式のCSSクラスをいい感じにソートするプラグインを入れておきます。cf. Automatic Class Sorting with Prettier - Tailwind CSS

npm i -D prettier @trivago/prettier-plugin-sort-imports prettier-plugin-tailwindcss

その他にやることとしては、Faviconの差し替えでしょうか。今回はfavicon.ioでまとめて生成しました。

Tailwindをv3 -> v4にアップグレード

ここでTailwindCSSをv4にアップグレードすることにします。Tailwind公式のUpgrade guideでマイグレーションツールが紹介されていたので、使います。

npx @tailwindcss/upgrade

Tailwindの設定ファイルの内容がグローバルCSSに移行されました。

さっそく開発サーバーがエラーを吐きました。

CssSyntaxError: tailwindcss: C:\path\to\src\app\_components\markdown-styles.module.css:1:1: Cannot apply unknown utility class `text-lg`. Are you using CSS modules or similar and missing `@reference`? https://tailwindcss.com/docs/functions-and-directives#reference-directive

@referenceをミッシングしているらしいのでCSS Modulesファイルの冒頭に参照をはります。

@reference "tailwindcss";

さらに、PrettierのTailwindプラグインが動作していないことにも気付きました。プラグインのREADMEを見たら、Tailwind v4の場合はtailwindStylesheetキーでCSSのエントリーポイントを特定しないといけないと書かれていました。

最終的に.prettierrcはこんな感じ。

{
  "trailingComma": "es5",
  "semi": true,
  "singleQuote": false,
  "plugins": [
    "@trivago/prettier-plugin-sort-imports",
    "prettier-plugin-tailwindcss"
  ],
  "importOrder": [
    "^react$",
    "^next$",
    "<BUILTIN_MODULES>",
    "<THIRD_PARTY_MODULES>",
    "^@/[^/]+/(.*)$",
    "^[./]"
  ],
  "tailwindStylesheet": "./src/app/globals.css"
}

SSGでビルドしてGitHub Pagesにデプロイする

結局サンプルをいったん更地にしてコンポーネントを作り直し、ダークモードも自分で実装してみたのですが、通常のReactアプリとは異なりUIがフリッカ―する問題があるので、少し手こずりましたね。その話は別記事にします。

SSGでビルドするにはnext.config.jsを以下のように設定しておきます。

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: "export",
  trailingSlash: true,
  distDir: "dist",
};
 
module.exports = nextConfig;

next buildコマンドでビルドすると静的HTMLが生成されます。次にnext startを使うとSSRになってしまうので、ローカルでの動作確認はnpx serve distコマンドを使います。

デプロイ先はお手軽さ優先でGitHub Pagesに。GitHub Actionsのワークフローで自動的にビルドとデプロイを実行します。

ワークフローを記述するYAMLファイルは、あらかじめNext.js用のテンプレートが用意されているので、ほぼデフォルトのまま使うことができます。変更の監視範囲(_postsapp)と出力フォルダ(outからdistに変更)の設定だけ変更しました。

ここまで作ったあとで気づいたのですが、Blog StarterよりもNext.js Portfolio StarterのほうがダイナミックOG画像生成やシンタックスハイライトがあらかじめ設定されており、使いやすいかもしれません。

現時点では、とりあえずページを表示できるだけの状態なので、改善を重ねて使いやすいものにしていきたいと思います。