iOS&Androidスマートフォン開発(Swift/Kotlin/React-Native) および Next.js/LaravelをはじめとしたWeb開発ならば、ぜひ創業13年の弊社にお任せください。ワンストップでお届けします。お問合せはこちらから

Next.js製ブログをメインプロジェクトの下の/blogでVercelに配信したい

  2023年07月24日 00:00 / - PV

yuku_tasのアイコン

こんにちは、Webサービス開発者のyuku_tasです。

簡単なプロフィール: MoldSpoon Inc.代表。開業から15年、業界に携わって20年。Webサイト/iOS/Androidアプリ開発から、データ分析業務・コンサル業務、ベンチャーから保険会社まで様々な案件を個人会社の形で請け負ってまいりました。詳しくはこちら

本記事のゴール

元々MoldSpoon Inc. のWebサイトが動いているNext.jsプロジェクトの下に、さらにもう一つ、Next.jsプロジェクトを作ってブログとして配信したいと考えました。

  • moldspoon.jp/blog 以下の全てのリクエストは子プロジェクト(ブログ)で補足
  • moldspoon.jp/ 以下の全てのリクエストは親プロジェクトで補足

作業

公式ドキュメントをあたったところ、rewriteという方法があるようです。

以下のように、別途Vercelにデプロイしているプロジェクトの固定ドメインにもリンクが貼れるようです。

vercel.json
{
  "rewrites": [
    {
      "source": "/blog",
      "destination": "https://moldspoon-blog.vercel.app/blog/blog"
    },
    {
      "source": "/blog/:match+",
      "destination": "https://moldspoon-blog.vercel.app/blog/:match+"
    }
  ]
}

こちらを親プロジェクトに vercel.jsonというファイル名でプロジェクトルート直下に作成。

続いて、子プロジェクトの next.config.jsに以下の設定を追加します。

(私は/blog以下にデプロイしたいのでそうしました)

next.config.js
const isProd = process.env.NODE_ENV === 'production';
const cdnPrefix = isProd ? '/blog' : '';

if (isProd && cdnPrefix) {
  console.log(`> You have customized the CDN prefix: ${cdnPrefix}.\n`);
}

const withMDX = require('@next/mdx')({
  extension: /\.(md|mdx)?$/,
  options: {
    rehypePlugins: [require('@mapbox/rehype-prism'), require('rehype-join-line')],
  },
});

/** @type {import('next').NextConfig} */
const nextConfig = {
  basePath: '/blog',
  assetPrefix: '/blog',
  async rewrites() {
    return [
      {
        source: "/blog",
        destination: "/blog/blog",
      },
      {
        source: "/blog/api/:path*",
        destination: "/api/:path*",
      },
      {
        source: "/blog/images/:query*",
        destination: '/_next/image/:query*'
      },
      {
        source: "/blog/_next/:path*",
        destination: "/_next/:path*",
      },
    ]
  },

  pageExtensions: ['jsx', 'js', 'mdx', 'md', 'ts', 'tsx'],
  generateEtags: false,
  poweredByHeader: false,
  env: {
    VERSION: require('./package.json').version,
  },

  redirects() {
    return [];
  },
};

module.exports = withMDX(nextConfig);

rewritesの各設定がないと、

  • https://moldspoon-blog.vercel.app/blog にリクエストした途端リダイレクトループ(308ステータス)に陥る (/blog => /blog/ => /blog とループする)
  • Javascriptファイルへのパスが疎通せず、画面が真っ白になる(UIの描画がされない)ので注意してください。

これで、

https://moldspoon.jp/blog => https://moldspoon-blog.vercel.app/blog

に転送ができるようになりました。リダイレクトでないので、遷移が1つ増えるとかもないはず...。

ポイントとしては、子プロジェクトのvercelドメインで、サブディレクトリのパスがついた状態で 遷移できるか否かをチェックすることが肝要です。上記例だと、

  • https://moldspoon-blog.vercel.app/blog 以下で全URLが見れるか(TOPしかrewriteが効いていない可能性がある)
  • react routerで遷移ができていても、URLの転送が効くかは別なので、その観点でも各ページでリロードして確認する

が作業完了までに必要になると思いました。

まとめ

大体の流れは以下でした。nginxやapacheのproxyと一緒で、リダイレクト系はどうしてもハマる時はハマっちゃいますね...

  • 親プロジェクトのvercel.jsonに rewrite()設定を追加
  • 子プロジェクトのnext.config.jsに basePath assetPrefix rewrite()を追加
  • 両方のプロジェクトをデプロイ

monorepoで管理するという方法もあったのですが、今回は大きなプロジェクトではないのであまり難しく考えずに 簡単な方を選んでいます。

Share Me!