私はフリーランスとして、ウェブサイト制作全般やPHP/Laravel等の開発をしています。JSも書きますが、普段はバックエンド寄り。
しかしながら、昨今のブームとして、モダンなフロントエンド開発の知識の必要性を感じています。ReactやVue.js等を使用したものですね。
とは言え私の顧客である小・零細企業のサービスサイトにはちょっと向いてないと思っていました。特にSPAは本当に100%静的サイトと同じくクロールしてくれるのか確証を持てないためです(今は問題無いとは言われますが)。
しかしNext.js/Nuxt.jsならSSG, SSRも簡単にできるっぽいしSEOの問題も全てクリアしそう。良さげ!
……ということで、普段バックエンド側の私が、Next.jsをインストールし、LaravelのAPIと連携するところまで挑戦してみることにしました。私と同じような境遇の方に、参考になることがあれば幸いです。
- 前提
- Laravelのインストール
- Next.jsのインストール
- Ok to proceed? (y)
- √ Would you like to use TypeScript? … No / Yes
- √ Would you like to use ESLint? … No / Yes
- ? Would you like to use Tailwind CSS? » No / Yes
- √ Would you like to use src/ directory? … No / Yes
- √ Would you like to use App Router? (recommended) … No / Yes
- ? Would you like to customize the default import alias (@/*)? » No / Yes
- まとめ
- 動作確認
- LaravelのAPIの準備
- Next.jsからLaravel APIを呼び出す
- 応用:1件ずつ表示してみる
- まとめ
前提
- 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プロジェクトが作成されます。特に難しいことはありません。
いつもは固有名でつけますが、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+クリック
で開くと、いつもの見慣れた表示が出ました。
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:3000
をCtrl+クリック
でアクセスすると、以下の様に表示されました。
成功です。はたしてこれが見慣れる日が来るのでしょうか。
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で TestController
の index
メソッドが呼び出されるようになります。
動作確認
http://localhost:8000/api/test
にアクセスしてみると……。
無事JSONが返ってくることが確認できました。
Next.jsからLaravel APIを呼び出す
先ほどのLaravelのAPIを、Next.jsから呼び出してみたいと思います。
新しいページを作成
VSCodeで、Next.js側のfrontend
ディレクトリを開き、app/api-test/page.tsx
ファイルを作成します。
コード例
私はゼロからコードを書くほど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;
実行結果
デザインはあれですが、以下の様に表示させることができました!
応用: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を表示するようにしています。
実際には、< 1 2 3 >のようなページング処理をすることが多いと思います。
また、今回は全件(3件)ロードしていますが、実際のWebアプリケーションで全件ロードを行うことは多くないでしょう。
このあたりはさらに仕様を検討しないといけなさそうですね。
まとめ
以上、Next.js/ReactとLaravelでAPI連携してみました。思ったよりは簡単にできたなと思います。
1つ前の記事で、Laravel BreezeでReactを触ってみるという記事を書きました。こちらもReact関連の手を広めようとしてのことですが、とてもではないですが両方一度に学ぶことはできません。
実務に活かすために、どちらから学んでいこうかなと模索中です。認証等も入るとまた難しさが違ってくるので、そのあたりも調査しないといけなさそうですね。
この調査は、続編も書いていきたいと思います。
コメント