Next.jsを使って静的なブログサイトを作成する(1)

はじめに

Next.jsBlog Starter Kit を使ったブログサイト作成手順のメモです。
一般のレンタルサーバにアップロード可能な静的コンテンツを作成します。

私の環境

  • OS: Windows 11 Home
  • ターミナル: PowerShell(v7.4.2)
  • エディタ: Visual Studio Code
  • Node.js: v20.12.2

Blog Starter Kit とは

Next.jsには様々なテンプレートが用意されており、Blog Starter Kit はブログ作成用テンプレートの一つです。簡易なマークダウンとTailwind CSSが使えます。

Node.jsをインストールする

以下の手順で、Node.jsをインストールします。

  1. https://nodejs.org を表示します。
  2. メニューの download をクリックします。
  3. Prebuilt Binaries をクリックします。
  4. 最新のLTSバージョン(今回はv20.12.2)、Windows、x64を選択します。
  5. Download Node.js をクリックします。
  6. ダウンロードしたZIPファイルを展開します。
  7. 展開したフォルダを適当な場所へ配置します。ここではCドライブ直下に配置します。「C:\node-v20.12.2-win-x64」直下にnode.exeが存在する状態です。
  8. Windowsの検索ボックスに システムの と入力します。
  9. 表示された システムの詳細設定の表示 をクリックします。
  10. 環境変数 をクリックします。
  11. 下側にあるシステム環境変数の Path を選択して 編集 をクリックします。
  12. 新規 をクリックして先ほどのフォルダのパスを入力します。ここでは「C:\node-v20.12.2-win-x64」を入力します。
  13. OKをクリックします。
  14. ターミナルを起動します。
  15. 下記コマンドによりバージョンが表示されれば成功です。
> node -v
v20.12.2
> npm -v
10.5.0

Nextプロジェクトを作成して表示する

適当なフォルダへ移動します。

> cd c:\website

プロジェクトを作成します。

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

パッケージのインストールが必要と言われたら yes を回答します。

作成されたフォルダへ移動します。

> cd blog_starter_app

開発モードで実行します。

> npx next dev

ブラウザでhttp://localhost:3000を表示して画面を確認してください。

サイトのタイトルを変更するには

src/app/_components/header.tsxをエディタで開いて、Blogのところを書き換えます。

const Header = () => {
  return (
    <h2 className="text-2xl md:text-4xl font-bold tracking-tight md:tracking-tighter leading-tight mb-20 mt-8 flex items-center">
      <Link href="/" className="hover:underline">
-       Blog
+       おいらのブログ
      </Link>
      .
    </h2>
  );
};

記事を追加してみる

プロジェクトのフォルダ内はこのようになってます。

BLOG_STARTER_APP
│  .gitignore
│  next-env.d.ts
│  package-lock.json
│  package.json
│  postcss.config.js
│  README.md
│  tailwind.config.ts
│  tsconfig.json
│
├─node_modules
│  └─(省略)
│
├─public
│  └─(省略)
│
├─src
│  └─(省略)
│
└─_posts
        dynamic-routing.md
        hello-world.md
        preview.md

「_posts」フォルダ内に拡張子.mdのファイルを作成すると記事が追加されます。
サンプル記事が入ってますのでこれらを参考に記事を追加します。

---
title: "九龍風水傳"
coverImage: "/assets/blog/preview/cover.jpg"
date: "1997-05-22T"
author:
  name: "阿J"
  picture: "/assets/blog/authors/jj.jpeg"
ogImage:
  url: "/img/gate.jpeg"
---

## ファイアの日

ブラウザをリロードして記事が追加されたことを確認してください。

Metadata

ところで、ターミナルを確認すると下記のようなエラーが表示されていると思います。

metadata.metadataBase is not set for resolving social open graph or twitter images, using "http://localhost:3000". See https://nextjs.org/docs/app/api-reference/functions/generate-metadata#metadatabase

リンク先をヒントに「src/app/layout.tsx」を編集します。
編集前はこうなってます。

export const metadata: Metadata = {
  title: `Next.js Blog Example with ${CMS_NAME}`,
  description: `A statically generated blog example using Next.js and ${CMS_NAME}.`,
  openGraph: {
    images: [HOME_OG_IMAGE_URL],
  },
};

metadataBaseの行を追加し、title、description、imagesも編集します。
以下は例です。値は各自のサイトに合わせて編集してください。

export const metadata: Metadata = {
  title: `MY AWESOME SITE`,
  description: ``,
  metadataBase: new URL('https://hogehoge.net/'),
  openGraph: {
    images: '/assets/og.png',
  },
};

imagesの画像は実在してなくてもエラーにはなりません。
以上によりさきほどのエラーは出なくなったはずです。

ビルド

ターミナルでの実行は一旦終了します。キーボードのCtrl+Cを押してください。
次にビルドを実行します。

> npx next build

ビルドが完了するのを待ちます。Failed とか error という単語が表示されてなければ成功です。
下記コマンドを実行し、ブラウザでhttp://localhost:3000を表示します。

> npx next start

ブラウザでは正常に表示されますが、ターミナルには次のようなエラーが表示されていました。

For production Image Optimization with Next.js, the optional 'sharp' package is strongly recommended. Run 'npm i sharp', and Next.js will use it automatically for Image Optimization.

警告に従い、画像最適化のためのsharpパッケージをインストールします。
Ctrl+Cでnpx next startを一旦終了してから

> npm i sharp

sharpをインストールできたら、再度ビルドからやり直します。

> npx next build
> npx next start

ターミナルにエラーが表示されなくなったことを確認します。

参考: https://nextjs.org/docs/messages/sharp-missing-in-production

静的エクスポート

エクスポートするために下記コマンドを実行したところエラーが発生しました。

> npx next export

The "next export" command has been removed in favor of "output: export" in next.config.js. Learn more: https://nextjs.org/docs/advanced-features/static-html-export

このコマンドはNext.jsのv14.0から使用できなくなったようです。エクスポートするには設定ファイルを編集する必要があります。
プロジェクトフォルダ直下(package.jsonと同じ場所)に「next.config.mjs」ファイルを作成します。

/** @type {import('next').NextConfig} */

const nextConfig = {
    output: "export",
};

export default nextConfig;

ドメイン下にサブパスが存在する場合、つまりhttps://hogehoge.netでなくhttps://hogehoge.net/fugaをサイトのルートにしたい場合はbasePathを設定します。

/** @type {import('next').NextConfig} */

const nextConfig = {
    output: "export",
    basePath: "/fuga",
};

export default nextConfig;

これでビルドしたときにoutフォルダ内に静的コンテンツがエクスポートされるようになりました。

> npx next build

静的エクスポートでは npx next start は使用できなくなります。
代わりに以下のコマンドを実行すると、エクスポート結果が表示されます。

> npx serve out

「OK to proceed?」には y を回答します。

ブラウザで確認するとカバーイメージが表示されていません。
静的エクスポートではImage Optimizationを無効にする必要があるようです。
先ほどの「next.config.mjs」を編集します。

/** @type {import('next').NextConfig} */

const nextConfig = {
    output: "export",
    images: {
        unoptimized: true
    },
};

export default nextConfig;

ビルドからやり直します。

> npx next build
> npx serve out

表示結果が問題ないことを確認します。

デプロイ

outフォルダの中身を本番環境へアップロードします。

なおGithub Pagesにアップロードした場合は、Jekyllの働きにより_nextフォルダが見えなくなって、CSSのスタイルが反映されないという問題が発生します。
リポジトリのトップに.nojekyllという名前の空ファイルを作成することで解決します。Jekyllが働かなくなりスタイルが反映されます。