Next.js で作った技術ブログを Cloud Storage に静的ホスティングした話

Next.js で Markdown ベースのブログを作り、
ビルドした静的ファイルを Google Cloud Storage(GCS)に置くだけで公開できる構成を作ったので、その手順をまとめます。

結論:Next.js + Markdown + GCS だけで、わりと簡単に技術ブログが作れます。


ゴール

  • トップページ:Markdown 記事を一覧表示
  • 記事ページ:Markdown → HTML 変換して表示
  • ホスティング:GCS で静的サイトをそのまま配信
  • フレームワーク:Next.js(App Router)
  • Cloud Storageのキャッシュ問題の解決

全体構成

ブログはシンプルに、以下のような構成です。

my-blog/
├── app/               # Next.js (App Router)
├── content/           # Markdown 記事
├── public/
└── out/               # 静的書き出し結果(ここを GCS に置く)

書いた Markdown は content/*.md に置くだけです。


Step 1. Next.js プロジェクトを作成

npx create-next-app my-blog --ts --app

Markdown を扱うために最低限のライブラリを追加。

npm install gray-matter marked

Step 2. Markdown を読み込んでページを生成

記事一覧(トップページ)

content/ 内の Markdown を読み込んで一覧を作っています。

import fs from "fs";
import matter from "gray-matter";

export default function Page() {
  const files = fs.readdirSync("content");
  const posts = files.map((file) => {
    const { data } = matter(fs.readFileSync(\`content/\${file}\`, "utf8"));
    return { ...data, slug: file.replace(".md", "") };
  });

  return (
    <div>
      <h1>技術ブログ</h1>
      {posts.map((p) => (
        <div key={p.slug}>
          <a href={\`posts/\${p.slug}.html\`}>{p.title}</a>
        </div>
      ))}
    </div>
  );
}

記事ページ(Markdown → HTML)

import fs from "fs";
import matter from "gray-matter";
import { marked } from "marked";

export default function PostPage({ params }) {
  const raw = fs.readFileSync(\`content/\${params.slug}.md\`, "utf8");
  const { data, content } = matter(raw);

  return (
    <article>
      <div dangerouslySetInnerHTML={{ __html: marked(content) }} />
    </article>
  );
}

Step 3. Next.js を静的書き出しにする

Next.js 16 以降は next export が廃止されたため、
next.config.jsoutput: "export" を設定します。

// next.config.js
const nextConfig = {
  output: "export",
};

module.exports = nextConfig;

これでビルドすると、すべて静的ファイルとして out/ に出力されます。

npm run build

出力例:

out/
├── index.html
├── posts/
│   └── hello-world.html
└── _next/

Step 4. Cloud Storage にアップロードして公開

バケット作成

gsutil mb -l asia-northeast1 gs://my-blog-site

公開権限(オブジェクトを誰でも読めるように)

gsutil iam ch allUsers:objectViewer gs://my-blog-site

静的ファイルをアップロード

gsutil -m cp -r out/* gs://my-blog-site/

Step 5. 公開 URL でアクセス

  • トップ
    https://storage.googleapis.com/my-blog-site/index.html

  • 記事
    https://storage.googleapis.com/my-blog-site/posts/hello-world.html

そのままブログとして公開できます。


ハマりどころ(軽く)

  • Billing Account が閉じていると GCS が読めない
  • next export は廃止なので output: "export" を使う必要がある
  • CSS や _next/static のパスが合わない時はキャッシュを疑う

まとめ

  • Next.js(App Router)でも静的書き出しが可能
  • Markdown で記事を書ける
  • Cloud Storage はそのまま静的ホスティングとして利用できる
  • カスタムドメインや Cloud CDN を組み合わせれば本格運用も可能

次にやりたいこと

  • 各タグをクリックすると、そのタグを持つ記事だけを表示するページ
  • 独自ドメインでブログを公開する
  • プロフィールの改修
  • ビルド・デプロイの自動化

「Next.js + Markdown + GCS」だけで、最小構成の技術ブログは普通に作れる
という話でした!