環境
- windows10
- DockerDesktop for Win 3.5.x
- Laravel 8.x
- PHP 8.x
- node v16.13.1
- npm 8.1.2
- Next.js 12.0.7
- React 17.0.1
- VsCode
- gitbash 2.32.0.1
ゴール
- Laravel側で簡単なAPIを作成し、Nextjs側からデータフェッチできること
- Next.jsでhtmlをプレレンダリングしてブラウザに表示できること
構成
前提
- Jamstack
・一般的なwebアプリやSPAとは異なり、サーバー側でビルドされた静的なHTMLを取得して、
ブラウザで表示するだけの構成
・動的なデータはサーバーでのビルド時にサーバー側でAPIやDBからデータを取得して
htmlに組み込む
・SEO評価が高いという観点から、Jamstackはブログやコーポレートサイトの作成に向いている
・データが更新されたタイミングで都度ビルドデプロイを行うことで最新の状態を維持可能 - 今回使用するソースコードのリポジトリはこちら
設定手順
開発環境の構築
Docker基盤
ソースコードをクローン
git clone https://github.com/masayan1126/next-laravel-docker.git
カレントをjumstack-sampleに変更
cd next-laravel-docker
各サービスのportを指定
.env.exampleをコピーして.envを作成し、各サービスのポートを指定してください。ご自身のマシンで空いているポートであれば何番でもOKです。
FRONTEND_PORT=
BACKEND_PORT=
DB_PORT=
PHPMYADMIN_PORT=
イメージビルド
docker-compose build
コンテナ起動
docker-compose up -d
フロントエンドの構築
frontendコンテナに入る
docker-compose exec frontend sh
nextjsアプリの作成
npm create next-app
Need to install the following packages:
create-next-app
Ok to proceed? (y) y
✔ What is your project named? … next-web
Creating a new Next.js app in /var/www/next-web.
カレントをnex-webに
cd next-web
ビルドして、開発用サーバーを起動する
npm run dev
wait - compiling / (client and server)...
event - compiled client and server successfully in 1338 ms (189 modules)
ブラウザでhttp://localhost:8020/(frontendの起動port)を表示。ウェルカム画面が表示されていれば、OK
バックエンドの構築
開発用サーバーの起動
backendコンテナに入る
docker-compose exec backend bash
laravelの新規プロジェクト作成
composer create-project laravel/laravel laravel-api
カレントをlaravel-apiに
cd laravel-api
開発用サーバー起動
--hostオプションで、コンテナ外から開発サーバーにアクセスできるようにする必要があるので注意(デフォルトは開発サーバーを起動しているホスト(今回の場合はDockerコンテナ)からしかアクセスを受け付けない)
php artisan serve --host=0.0.0.0
ブラウザでhttp://localhost:9020/(backendの起動port)を表示。ウェルカム画面が表示されていれば、OK
API構築
環境変数としてfrontendのurl等を指定する
api/laravel-api/.env
DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=db_next_laravel
DB_USERNAME=root
DB_PASSWORD=root
FRONTEND_URL=http://localhost:8020
cors.phpに追記
api/laravel-api/config/cors.php
<?php
return[
'paths'=>['api/*', 'sanctum/csrf-cookie'],
'allowed_methods'=>['*'],
'allowed_origins'=>[env('FRONTEND_URL', 'http://localhost')], // 先ほどの環境変数
'allowed_origins_patterns'=>[],
..割愛
'supports_credentials'=>true, // falseをtrueに変更
];
api/booksを叩くと、本の配列が返ってくる簡易API作成
api/laravel-api/routes/api.php
Route::get("/books", function () {
return ["book1", "book2", "book3"];
});
ここまでで、環境構築はいったん完了です
動作確認
APIからデータフェッチング
axiosでデータ取得
frontendコンテナ内で実行
npm install axios
frontend/next-web/libs/ にaxios.jsを作成
import Axios from "axios";
const axios = Axios.create({
baseURL: "http://localhost:9020",
headers: {
"X-Requested-With": "XMLHttpRequest",
},
withCredentials: true,
});
export default axios;
frontend/next-web/pages/index.js
...割愛
import axios from "../libs/axios";
import React, { useEffect } from 'react';
export default function Home() {
useEffect(() => {
axios.get("/api/books").then((res) => {
const data = res.data;
console.log(data);
});
}, []);
...割愛
}
APIから取得したデータがログに出力されていればOK
プレレンダリングする
基本
- プリレンダリングとは、簡単にいうと事前にサーバー側でHTMLを生成すること
- サーバー側でhtmlが生成されているかについては、ブラウザ側のjsを無効にして確認するとよい
- 無効にした状態で、サーバー側で生成されたhtmlを画面上に描画できることがこの記事のゴール
- ローカルでプリレンダリングを確認するには、以下の手順で行うとよい
npm run buildしてhtml,js,cssを出力し、npm run startで実行する(buildの結果物は.next/server/pages以下に生成される) - npm run devでは、動作確認できないので注意(すべてSSR(Server-side Rendering)になるため)
手順
ブラウザでJsを無効にする
Ctrl + Shift + P からjavascriptと入力し、無効にするを選択
この状態でブラウザをリロードすると、下図のようにjavascriptによりhtmlが生成できないため、もとのhtml要素しか表示されていない
Js無効状態でビルドする
Jsは無効にしたまま、frontendのコンテナ内で以下を実行して、本番用ビルドする
npm run build
npm run start
このように、jsとcssがあたった状態でビルドされたhtmlが表示されればOK
ハマりがちなエラー
余談ですが、Next.jsでdocumentやwindowといったクライアントサイドで使用可能なグローバル変数をそのまま使用するとそのような変数は定義されていないとエラーが発生します
理由は簡単で、サーバーサイドでブラウザ用のグローバル変数を使おうとしているためです
Next.jsはサーバーサイド、クライアントサイド両方で動くフレームワーク。そのため、定義したソースはサーバー、ブラウザ両方の環境で実行される可能性があるため、if (process.browser)でブラウザ上で実行する処理であるという判定を入れれば、エラーが生じなくなる
if (process.browser) {
// windowやdocumentを使う処理を記述
window.onpopstate = function (e) {
...
Typescriptの導入
frontendコンテナで以下を実行。tsconfig.jsonにデフォルトの設定が書き込まれる(すごい)
/var/www/next-web
touch tsconfig.json
npm install --dev typescript @types/react @types/node
npm run dev
atomicデザイン用にフォルダ構成を変える
ソースコードのディレクトリをsrc/に変更
tsconfig.jsonを編集して、srcは以下のファイルでソースコードを一元管理できるようにする
{
"compilerOptions": {
"target": "es5",
"baseUrl": "src/", // 追記
"rootDir": "src/", // 追記
以下のようにディレクトリ構造を変更する
next-web
└src
└components
└pages
└styles
└libs
index.jsなどをindex.tsxに変更し、ビルドしてエラーがでなければ成功
atomicデザイン用のディレクトリを追加
src直下に以下のようにディレクトリを追加しました
src
└components
└atomic
└Atoms
└Molecules
└Organisms
└Pages
└shared
Tailwind Cssを導入
依存関係のインストール、tailwindcss初期化
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
frontend\next-web\tailwind.config.js
tailwindを使用するファイルの拡張子を指定
module.exports = {
// 追加
content: [
'**/*.ts',
'**/*.tsx',
'**/*.jsx',
'**/*.js'
],
theme: {
extend: {},
},
plugins: [],
}
追加
frontend\next-web\src\styles\globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
styled-componentsを使用している場合のbabelの設定
サーバーサイドでもstyled-componentsが機能するように設定する必要がある
npm install --save-dev babel-plugin-styled-components
or
yarn add -D babel-plugin-styled-components
プロジェクトのルートに.babelrcを作成
{
"presets": [
"next/babel"
],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true,
}
]
]
}
以上です。次回以降は何をやるか考えてないですが、何か思いついたら実装して動画にしたいと思います。
まとめ
いかがでしたでしょうか。本記事は、Next.jsとLaravelでJamstackなWebサービスの環境構築を行うための手順について紹介している記事になります。この構成で構築すれば、とりあえず現状のモダンなアプリケーションは作成できるであろうという構成にしています。