Laravel 11 + React + TypeScript 環境を作る！！

# なぜこの記事を書いているか？

最近Laravel 10 + React + TypeScriptで案件をやっています。先日Laravelが11になったので、それを記念（？）して、Laravel 11ではどうするのかを調べつつまとめてみたいと思います。

# 環境

MacBook Pro 16' 2023 (M2 Max)
macOS Sonoma
Laravel 11.0.6
React 18.2.0
TypeScript 5.4.5

# PHPのセットアップ

基本的には [以前の記事](https://qiita.com/uehatsu/items/7d03f8a48b2ec68681b3) をトレースするだけですが、念のため記載しておきたいと思います。

## anyenv, phpenv をインストール

特に変更はないので、先達の資料をそのままリンク貼ります。

https://qiita.com/hamakou108/items/4744818dd166191c3e6b

[以前の記事](https://qiita.com/uehatsu/items/7d03f8a48b2ec68681b3) でも書いてますが、phpenv installでビルドするのは色々と問題が多いので辞めてしまいました。

## PHPのインストール
Homebrewを使ってインストールします。

```bash:Terminal
brew install php@8.0
brew install php@8.1
brew install php@8.2
brew install php
```

## phpenvへの設定の反映

phpenvの設定が終わっていると、~/.anyenv/envs/phpenv/versionsというディレクトリが出来ているはずです。出来ていない場合は設定をしてからphpenv versionsを実行してみてください。
それでは設定を反映させます。バージョン番号はその時のHomebrewでインストールされる最新の物に読み替えてください。

```bash:Terminal
cd ~/.anyenv/envs/phpenv/versions/
ln -s /usr/local/Cellar/php@8.0/8.0.30_1
ln -s /usr/local/Cellar/php@8.1/8.1.27_1
ln -s /usr/local/Cellar/php@8.2/8.2.18
ln -s /usr/local/Cellar/php/8.3.6
phpenv global 8.3.6
```

この状態で`phpenv versions`を実行すると以下のような表示になるはずです。

```bash:Terminal
phpenv versions
  system
  8.0.30_1
  8.1.27_1
  8.2.18 (set by /Users/foobar/.anyenv/envs/phpenv/version)
* 8.3.6
```

今回はこのPHP 8.3.6でLaravel 11をインストールしていきます。

# Laravel 11のインストール、他

## composer create-project の実行

以下のコマンドで2024/04/12現在でLaravel 11.0.6がインストールされます。

```bash:Terminal
composer create-project laravel/laravel foo_bar_test
```

## Laravel Sailの設定

```bash:Terminal
php artisan sail:install

→ mysql, mailpit, selenium を選択して、Enter
```

mysql, mailpit, selenium のDockerイメージをpullした後、Laravel実行用のDockerイメージのビルドが始まります。しばらく時間がかかります。

sailコマンドを簡単にアクセスさせるためにエイリアスを作っておきます。書き終わった後に`exec $SHELL -l`で.profileを読み込んでおきます。

```zsh:~/.zprofile
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
```

```zsh:Terminal
sail up
```

## 地域・ローカライズ周りの設定

Laravel 11から.envで設定するようになったんですね。こちらの方がスマートです。

```diff:.env / .env.example
- APP_TIMEZONE=UTC
+ APP_TIMEZONE=Asia/Tokyo

- APP_LOCALE=en
+ APP_LOCALE=ja

- APP_FAKER_LOCALE=en_US
+ APP_FAKER_LOCALE=ja_JP
```

## Laravel-Lang周りの設定

多言語対応のため、Laravel-Lang/langを利用します。設定にはLaravel-Lang/publisherを用います。

```bash:Terminal
sail composer require laravel-lang/publisher laravel-lang/lang --dev
sail artisan lang:add ja
```

## Laravelのmigration

```bash:Terminal
sail artisan migrate
```

# React + TypeScriptの設定

## モジュールのインストール

```bash:Terminal
sail npm install -D \
    react react-dom @types/react @types/react-dom \
    @vitejs/plugin-react \
    typescript \
    sass \
    @types/node
```

## `tsconfig.json` の作成

```json:tsconfig.json
{
    "compilerOptions": {
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "jsx": "react-jsx",
        "esModuleInterop": true,
        "baseUrl": "./resources/ts/",
        "paths": {
            "@/*": ["*"],
        },
    },
}
```

## `vite.config.ts` の作成

`vite.config.js` から `vite.config.ts` にリネームした上で以下のように修正します。

```typescript:vite.config.ts
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import react from "@vitejs/plugin-react";

export default defineConfig({
    resolve: {
        alias: [
            { find: "@/", replacement: `${__dirname}/resources/ts/`}
        ],
    },
    plugins: [
        laravel({
            refresh: true,

            input: ["resources/sass/app.scss", "resources/ts/index.tsx"],
        }),
        react(),
    ],
});
```

## `resources/{css|js}`, `resources/views/welcome.blade.php` の削除

`resouces/css`　と `resources/js` を中身ごと削除します。
`redouces/views/welcome.blade.php` を削除します。

## `index.tsx` の作成

`resources/ts/` ディレクトリを作り、その下に `index.tsx` ファイルを作成します。

```tsx:index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';

const container = document.getElementById('app');
const root = createRoot(container!);

root.render(
    <div className="foo-bar-app">
        Laravel React+Typescript環境構築
    </div>
);
```

## `app.scss` の作成

`resources/sass/` ディレクトリを作り、その下に `app.scss` ファイルを作成します。

```scss:app.scss
.foo-bar-app {
  color: blue;
}
```

## `index.blade.php` の作成

`resources/views/index.blade.php` を作成し、以下の内容にします。

```php:index.blace.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Foo Bar</title>

        @viteReactRefresh
        @vite(['resources/sass/app.scss', 'resources/ts/index.tsx'])
    </head>

    <body>
        <div id="app"></div>
    </body>
</html>
```

## `routes/web.php` の更新

以下に修正します。

```php:routes/web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('/{any}', function () {
    return view('index');
})->where('any', '.*');
```

## viteで諸々を生成

```bash:Terminal
sail npm run dev

or

sail npm run build
```

## ブラウザでアクセス

`http://localhost/`にアクセスし、以下のような表示が出れば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65508/4da7da99-cb04-17b1-b899-3704908d6d73.png)

# まとめ

特に難しい事はしていません。バックエンドもLaravelである必要は今回は全くありません。まずは環境ができたので、この後色々と設定変更なり実際の実装などを進める事になります。また改めて記事にしたいと思います。