普段バックエンドの私がNext.jsで、Laravel APIとの連携を試してみる

Laravel Next.jsで、Laravel APIとの連携を試す Laravel
※当サイトはアフィリエイト広告を掲載しています。

私はフリーランスとして、ウェブサイト制作全般やPHP/Laravel等の開発をしています。JSも書きますが、普段はバックエンド寄り。

しかしながら、昨今のブームとして、モダンなフロントエンド開発の知識の必要性を感じています。ReactやVue.js等を使用したものですね。

とは言え私の顧客である小・零細企業のサービスサイトにはちょっと向いてないと思っていました。特にSPAは本当に100%静的サイトと同じくクロールしてくれるのか確証を持てないためです(今は問題無いとは言われますが)。

しかしNext.js/Nuxt.jsならSSG, SSRも簡単にできるっぽいしSEOの問題も全てクリアしそう。良さげ!

……ということで、普段バックエンド側の私が、Next.jsをインストールし、LaravelのAPIと連携するところまで挑戦してみることにしました。私と同じような境遇の方に、参考になることがあれば幸いです。

一応、簡単に用語を補足しておきます。詳しくはググってね!

  • SPA – シングルページアプリケーション(HTMLは初回のみ、あとはJSでロード)
  • MPA – マルチページアプリケーション(毎回HTMLをリクエストする)
  • SSG – サーバサイドジェネレーション(HTMLをビルド時に姿勢)
  • SSR – サーバサイドレンダリング(HTMLをリクエスト時に生成)

前提

  • Windows11 Professional環境です。
  • Composerをあらかじめ用意する必要があります。
  • 今回はD:\www\laranext.localというディレクトリに、Next.jsとLaravelのプロジェクトを作ります。
  • 分かりやすくするため、Next.jsはfrontend、Laravelはbackendというプロジェクト名にします。適宜読みかえてください。

Laravelのインストール

任意のディレクトリ、ここではD:\www\laranext.localをターミナル・コマンドプロントで開きます。

おなじみの以下のコマンドでLaravelプロジェクトをインストールします。

composer create-project --prefer-dist laravel/laravel backend

backendというサブディレクトリにLaravelプロジェクトが作成されます。特に難しいことはありません。

Lara
Lara

いつもは固有名でつけますが、ChatGPT先生の指導でbackendとしました。直接的で分かりやすいものですね。

Next.jsのインストール

次に、Next.jsプロジェクトをインストールします。

npx create-next-app@latest frontend

これが終わればfrontendというサブディレクトリにNext.jsプロジェクトが作成されます。

……が、一筋縄ではいきません。インストール時、色々と聞かれます。

Yes/Noを左右キーで選びエンターで選択可能なのですが、慣れないとわかりづらいです。1つずつ見ていきましょう。

Ok to proceed? (y)

いわずもがなで、続行してもよろしいですか?とのこと。Enterで進めます。

√ Would you like to use TypeScript? … No / Yes

TypeScriptを使いますか?とのことです。

TypeScriptはJavaScriptに静的型付けを追加したもので、大規模なプロジェクトやチームワークにおいてエラーを早期に発見しやすくなります。

コードの品質と保守性が向上する反面、慣れないとより難しくなります。私は慣れたいのでYes(デフォルト)にしました。

√ Would you like to use ESLint? … No / Yes

ESLint使いますか?とのことです。

ESLintはコードの品質を向上させ、一貫したコーディングスタイルを維持。コードエラーや潜在的な問題を早期に検出し、修正を容易にしてくれるとのこと。こちらもYes(デフォルト)にします。

? Would you like to use Tailwind CSS? » No / Yes

Tailwind CSS使いますか?とのことです。

Tailwind CSSはユーティリティファーストのCSSフレームワークです。ご存じ&使いたい方は使えばOK。

私はまだいまいち有用性がわからないので、今回はNoに変更しました。

√ Would you like to use src/ directory? … No / Yes

すべてのソースファイル(コンポーネント、ページ、スタイルなど)を src/ ディレクトリ内に整理するかどうかです。

プロジェクトの構造が整理され、大規模なアプリケーションでの管理が容易になる。……とのことですが、小規模なプロジェクトではNoもありそうです。

私はNo(デフォルト)にしました。

√ Would you like to use App Router? (recommended) … No / Yes

Next.js 13以降ではこのApp Routerというのが導入されたようで、これを使うかということです。

従来のPages Routerよりも今はこちらがお勧めとのことで、Yes(デフォルト)で。

App Routerは情報が少ないと言われていましたが、今はそんなことないでしょう(適当)。

? Would you like to customize the default import alias (@/*)? » No / Yes

インポートパスのエイリアス(@/*)をカスタマイズするかということです。これはNo(デフォルト)にします。

まとめ

というわけで、私は以下の様にしました。

Ok to proceed? (y)
√ Would you like to use TypeScript? ... Yes
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... No
√ Would you like to use `src/` directory? ... No
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@/*)? ... No

TailwindCSSをNoにしただけで、後はデフォルトでインストールしました。本ページの内容に沿って進めたい方は、同じにしてみてください。

この部分に関しては各々の好みなどもあると思いますので、やってみなければわからなそうです。

唯一、App Routerを使うか・使わないかは開発に大きく変わってくることでしょう。ですがわざわざ「お勧め」とあるので、App Routerの方が将来性がありそうです。

動作確認

Laravelの動作確認

backend ディレクトリに移動し、Laravelの開発サーバーを起動します。コマンドは以下です。

cd backend
php artisan serve

以下の様になりました。

PS D:\www\laranext.local\backend> php artisan serve

   INFO  Server running on 
http://127.0.0.1:8000
. Press Ctrl+C to stop the server

http://127.0.0.1:8000部分をCtrl+クリックで開くと、いつもの見慣れた表示が出ました。

Laravelインストール直後の画面

Next.jsの動作確認

新しいコマンドプロンプトまたはターミナルウィンドウを開き、frontend ディレクトリに移動します。
そしてNext.jsの開発サーバーを起動します。(cdの部分は適宜調整してください)

cd frontend
npm run dev

すると、以下の様に起動します。

PS D:\www\laranext.local\frontend> npm run dev

> frontend@0.1.0 dev
> next dev

   ▲ Next.js 14.0.4
   - Local:        http://localhost:3000

 ✓ Ready in 1684ms

こちらもhttp://localhost:3000Ctrl+クリックでアクセスすると、以下の様に表示されました。

Next.jsインストール直後の画面

成功です。はたしてこれが見慣れる日が来るのでしょうか。

LaravelのAPIの準備

LaravelとNext.jsが単独で動作することは確認できました。次に、双方が連携して動作するかをテストするために、Laravel側で簡単なAPIを実装してみます。

コントローラーの作成

Laravelプロジェクトのルートディレクトリで、次のコマンドを実行して新しいコントローラーを作成します。

php artisan make:controller TestController

app/Http/Controllers/TestController.php が作成されますので、以下の様に修正します。

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index()
    {
        // ダミーデータの配列を作成
        $data = [
            ['id' => 1, 'name' => '鈴木イチロウ', 'description' => 'Description for鈴木イチロウ'],
            ['id' => 2, 'name' => '山田タロウ',   'description' => 'Description for 山田タロウ'],
            ['id' => 3, 'name' => '伊藤シンジ',   'description' => 'Description for 伊藤シンジ'],
        ];

        // JSONレスポンスとしてデータを返す
        return response()->json($data);
    }
}

ここではindexメソッドで、単純なJSONレスポンスを返すようにしています。

APIルートを設定

routes/api.php ファイルを開き、先ほど作成したコントローラのメソッドにマッピングします。

use App\Http\Controllers\TestController;

Route::get('/test', [TestController::class, 'index']);

この指定により、/api/test のURLで TestControllerindex メソッドが呼び出されるようになります。

動作確認

http://localhost:8000/api/test にアクセスしてみると……。

生JSONをブラウザで表示中の画面

無事JSONが返ってくることが確認できました。

生JSONの表示はブラウザによって異なりますので、環境により上記スクリーンショットとちょっと違うかもしれません。

Next.jsからLaravel APIを呼び出す

先ほどのLaravelのAPIを、Next.jsから呼び出してみたいと思います。

新しいページを作成

VSCodeで、Next.js側のfrontendディレクトリを開き、app/api-test/page.tsx ファイルを作成します。

これはApp Router&TypeScriptを使用している前提です。

コード例

私はゼロからコードを書くほどNext.js/Reactの知識が無いので、ChatGPT先生にご教示いただいたコードです。

'use client';
import React, { useState, useEffect } from 'react';

// APIレスポンスの型を配列にする
interface ApiResponseItem {
    id: number;
    name: string;
    description: string;
}

const ApiTest: React.FC = () => {
    const [data, setData] = useState<ApiResponseItem[]>([]);

    useEffect(() => {
        fetch('http://localhost:8000/api/test')
            .then(response => response.json())
            .then((data: ApiResponseItem[]) => setData(data))
            .catch(error => console.error('Error fetching data:', error));
    }, []);

    return (
        <div>
            <h1>API Test</h1>
            {data.length > 0 ? (
                <div>
                    <h2>Data Received</h2>
                    {data.map((item) => (
                        <div key={item.id}>
                            <h3>{item.name}</h3>
                            <p>{item.description}</p>
                        </div>
                    ))}
                </div>
            ) : (
                <p>Loading data...</p>
            )}
        </div>
    );
};

export default ApiTest;

実行結果

デザインはあれですが、以下の様に表示させることができました!

Laravelが出力するAPIをNext.jsで表示したスクリーンショット

応用:1件ずつ表示してみる

実際のWebアプリケーションでは、X件ずつ表示……なんてこともできないとダメです。Next.jsではどうやるのかなと思い、ChatGPT先生に教えてもらいました。

コード例

page.tsxを以下の様に改修します。

'use client';
import React, { useState, useEffect } from 'react';

interface ApiResponseItem {
    id: number;
    name: string;
    description: string;
}

const ApiTest: React.FC = () => {
    const [data, setData] = useState<ApiResponseItem[]>([]);
    const [currentPage, setCurrentPage] = useState(0);

    useEffect(() => {
        fetch('http://localhost:8000/api/test')
            .then(response => response.json())
            .then((data: ApiResponseItem[]) => setData(data))
            .catch(error => console.error('Error fetching data:', error));
    }, []);

    const itemsPerPage = 1;
    const totalPages = Math.ceil(data.length / itemsPerPage);
    const currentPageData = data.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage);

    const goToNextPage = () => {
        setCurrentPage((prevPage) => Math.min(prevPage + 1, totalPages - 1));
    };

    const goToPreviousPage = () => {
        setCurrentPage((prevPage) => Math.max(prevPage - 1, 0));
    };

    return (
        <div>
            <h1>API Test</h1>
            {currentPageData.map((item) => (
                <div key={item.id}>
                    <h3>ID:{item.id} {item.name}</h3>
                    <p>{item.description}</p>
                </div>
            ))}
            <div>
                <button onClick={goToPreviousPage} disabled={currentPage === 0}>Previous</button>
                <button onClick={goToNextPage} disabled={currentPage === totalPages - 1}>Next</button>
            </div>
        </div>
    );
};

export default ApiTest;

こんな感じです。3件分を1件ずつ表示し、進んだり戻ったりすることができるようになりました。※今回、前後関係が分かりやすいように、名前の前にIDを表示するようにしています。

Next.jsでページング処理するアニメーション

実際には、< 1 2 3 >のようなページング処理をすることが多いと思います。

また、今回は全件(3件)ロードしていますが、実際のWebアプリケーションで全件ロードを行うことは多くないでしょう。

このあたりはさらに仕様を検討しないといけなさそうですね。

まとめ

以上、Next.js/ReactとLaravelでAPI連携してみました。思ったよりは簡単にできたなと思います。

1つ前の記事で、Laravel BreezeでReactを触ってみるという記事を書きました。こちらもReact関連の手を広めようとしてのことですが、とてもではないですが両方一度に学ぶことはできません。

実務に活かすために、どちらから学んでいこうかなと模索中です。認証等も入るとまた難しさが違ってくるので、そのあたりも調査しないといけなさそうですね。

この調査は、続編も書いていきたいと思います。

コメント

タイトルとURLをコピーしました