使用するバージョン
node : 16.12.0
next : 11.1.2
react : 17.0.2
laravel : 8.65

LaravelとNext.jsの使い方は下記ページも参考にしてください。

Laravel8でシンプルなCMSを作るチュートリアル[2020年版]
Next.js入門(TypeScript版)

プロジェクトの作成

今回はLaravelとNext.jsの2つのディクトリを作ります。
最初に空のディレクトリを作り、カレントにします。

$ mkdir laravel-next
$ cd laravel-next

Laravelのインストール。ディレクトリ名はapiにします。

$ composer create-project laravel/laravel api

次はNext.jsのインストール

$ yarn create next-app --typescript

プロジェクト名を聞かれるのでclientにします。

? What is your project named? › client

ここまでやるとディレクトリ構造はこんな感じになっていると思います。

laravel-next
 ├ api
 │ └ Laravelが入っている
 └ client
   └ Next.jsが入っている

Laravelの設定

Next.jsと連携するために設定を編集します。
今回はビルドインサーバーで動作確認します。
デフォルトだとNext.jsのポートはlocalhost:3000なので、.envに追加します。

api/.env

FRONTEND_URL=http://localhost:3000

envの設定をオプションから使えるように下記を追加します。

api/config/app.php

'frontend_url' => env('FRONTEND_URL', 'http://localhost'),

CORSの設定をして、envで設定したURLと通信できるようにします。
変更するのはallowed_originssupports_credentialsです。

api/config/cors.php

<?php
return [
	'paths' => ['api/*', 'sanctum/csrf-cookie'],

	'allowed_methods' => ['*'],

	'allowed_origins' => [config('app.frontend_url')], // 変更

	'allowed_origins_patterns' => [],

	'allowed_headers' => ['*'],

	'exposed_headers' => [],

	'max_age' => 0,

	'supports_credentials' => true, // 変更
];

動作確認用に簡単な文字を表示返すだけのAPIを作ります。

api/routes/api.php

Route::get('/hello', function () {
	return 'Hello Next.js';
});

Laraelのビルドインサーバーを起動して、

$ cd api
$ php artisan serv

下記にアクセスして文字が表示されることを確認してください。

http://localhost:8000/api/hello

Next.jsの設定

作成するソースファイルを一つのディレクトリで管理できるように設定します。
tsconfig.jsonを下記のように編集します。

client/tsconfig.json

{
	"compilerOptions": {
	  // ...
	  "baseUrl": "src/",
	  "paths": {
		"@/*": ["./*"]
	  }
	},
	// ...
  }

これでsrcがルートとなるので、pagesstylessrcに移動します。
また、pathsを設定したのでインポートするときに@からのルートパスが使用できるようになります。

次に使用するライブラリをインストールします。

$ yarn add swr
$ yarn add axios

下記ファイルを作成し、Axiosの初期設定をします。

client/src/libs/axios.ts

import Axios from 'axios'

const axios = Axios.create({
	baseURL: 'http://localhost:8000',
	headers: {
		'X-Requested-With': 'XMLHttpRequest',
	},
	withCredentials: true,
})

export default axios

Axiosを使うときは基本このファイルと通すことになります。

次に、Laravelで作成した、hello API確認用のページを作成します。

client/src/pages/hello.tsx

import type { NextPage } from 'next'
import useSWR from 'swr'
import axios from '@/libs/axios'

const Hello: NextPage = () => {
	const { data, error } = useSWR('/api/hello', () =>
	axios
		.get('/api/hello')
		.then((res: any) => res.data)
	)
	
	if (error) return <div>エラーが発生しました</div>
	if (!data) return <div>読み込み中</div>
	return (
	<div>
		<h1>ようこそ</h1>
		<p>{data}</p>
	</div>
	)
}

export default Hello

Next.jsのビルドインサーバーを起動します。
Laravelの方も起動したままにしますので、もうひとつターミナルを開きましょう。

$ cd client
$ yarn dev

下記にアクセスしてLaravelで設定した文字「Hello Next.js」が表示されることを確認してください。

http://localhost:3000/hello

Laravelのpublicディレクトリにビルド

ここは最終的にどのような環境で運用するかにもよると思うのですが、今回はNext.jsのビルドをLaravelのpublicディレクトリにしてみます。

Laravelのpublicディレクトリから必要なファイルをNext.jsのpublicにコピーします。

$ cp api/public/index.php client/public/index.php
$ cp api/public/.htaccess client/public/.htaccess

package.jsonbuildを編集して書き出し先のディレクトリを変更します。

client/package.json

"scripts": {
	"dev": "next dev",
	"build": "next build && next export -o ../api/public",
	"start": "next start",
	"lint": "next lint"
},

clientディレクトリでビルドコマンドを実行します。

$ yarn build

api/publicに書き出されていることを確認してください。

トップページにアクセスするとLaravelのwebcomeページが表示されるので、index.htmlが表示されるようにルートを変更します。
web.phpを下記のようにします。

api/routes/web.php

Route::get('/', function () {
	return \File::get(public_path() . '/index.html');
});

LaravelのビルドインサーバーにアクセスしてNext.jsで作成したファイルが表示されることを確認できれば完成です。

http://localhost:8000/hello.html

そのままではないですが、Githubにサンプルあります。

laravel-nextjs-example