カスタムサーバー

デフォルトでは、Next.jsにはnext startで起動する独自のサーバーが含まれています。既存のバックエンドがある場合でも、Next.jsと一緒に使用できます(これはカスタムサーバーではありません)。カスタムNext.jsサーバーを使用すると、カスタムサーバーパターンを利用するためにプログラムで100%サーバーを起動できます。ほとんどの場合、これは必要ありませんが、完全なカスタマイズのために利用可能です。

知っておくと良いこと:

  • カスタムサーバーの使用を決定する前に、Next.jsの統合ルーターがアプリの要件を満たせない場合にのみ使用するようにしてください。カスタムサーバーを使用すると、サーバーレス関数や**自動静的最適化**などの重要なパフォーマンス最適化が失われます。
  • カスタムサーバーはVercelにデプロイできません
  • スタンドアロン出力モードでは、カスタムサーバーファイルはトレースされず、代わりに最小限のserver.jsファイルが別途出力されます。

以下のカスタムサーバーの例を見てみましょう:

server.js
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// ミドルウェア使用時は`hostname`と`port`を以下に指定する必要があります
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer(async (req, res) => {
    try {
      // `url.parse`の第2引数に`true`を渡すことを忘れないでください。
      // これによりURLのクエリ部分が解析されます。
      const parsedUrl = parse(req.url, true)
      const { pathname, query } = parsedUrl

      if (pathname === '/a') {
        await app.render(req, res, '/a', query)
      } else if (pathname === '/b') {
        await app.render(req, res, '/b', query)
      } else {
        await handle(req, res, parsedUrl)
      }
    } catch (err) {
      console.error('リクエスト処理中にエラーが発生しました', req.url, err)
      res.statusCode = 500
      res.end('内部サーバーエラー')
    }
  })
    .once('error', (err) => {
      console.error(err)
      process.exit(1)
    })
    .listen(port, () => {
      console.log(`> http://${hostname}:${port} で準備完了`)
    })
})

server.jsはbabelやwebpackを通りません。このファイルで使用する構文とソースが、実行中のNode.jsバージョンと互換性があることを確認してください。

カスタムサーバーを実行するには、package.jsonscriptsを次のように更新します:

package.json
{
  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "NODE_ENV=production node server.js"
  }
}

カスタムサーバーは、Next.jsアプリケーションとサーバーを接続するために以下のインポートを使用します:

const next = require('next')
const app = next({})

上記のnextインポートは、以下のオプションを持つオブジェクトを受け取る関数です:

オプションタイプ説明
confObjectnext.config.jsで使用するのと同じオブジェクト。デフォルトは{}
customServerBoolean(オプション)Next.jsによってサーバーが作成された場合はfalseに設定
devBoolean(オプション)Next.jsを開発モードで起動するかどうか。デフォルトはfalse
dirString(オプション)Next.jsプロジェクトの場所。デフォルトは'.'
quietBoolean(オプション)サーバー情報を含むエラーメッセージを非表示にする。デフォルトはfalse
hostnameString(オプション)サーバーが動作しているホスト名
portNumber(オプション)サーバーが動作しているポート番号
httpServernode:http#Server(オプション)Next.jsが動作しているHTTPサーバー

返されたappは、必要に応じてNext.jsにリクエストを処理させるために使用できます。

ファイルシステムルーティングの無効化

デフォルトでは、Nextpagesフォルダ内の各ファイルをファイル名に一致するパス名で提供します。カスタムサーバーを使用している場合、この動作により複数のパスから同じコンテンツが提供される可能性があり、SEOやUXに問題が生じる可能性があります。

この動作を無効にし、pages内のファイルに基づくルーティングを防ぐには、next.config.jsを開き、useFileSystemPublicRoutes設定を無効にします:

next.config.js
module.exports = {
  useFileSystemPublicRoutes: false,
}

useFileSystemPublicRoutesはSSRからのファイル名ルートを無効にしますが、クライアントサイドルーティングではこれらのパスにアクセスできる場合があります。このオプションを使用する場合は、プログラム的に不要なルートへのナビゲーションを防ぐ必要があります。

また、クライアントサイドルーターを設定して、ファイル名ルートへのクライアントサイドリダイレクトを禁止することもできます。詳細はrouter.beforePopStateを参照してください。