Laravel 8 Breeze を React + TypeScript + sass に対応させる。

タイトルの通りです。
色々、特に設定ファイルの書き方で詰まったのでメモ。

フロントエンドが React + TypeScript で、
かつ Laravel Breeze の inertiajs が最高で、出来れば使いたかったのと、
TailwindCss の `@apply` も好きで、sass で使いたかったので。

### 環境 (僕自身は Docker です)
- Mac 11.5.1(Big Sur)
- Docker 20.10.7
- docker-compose 1.29.2
- PHP 7.4.28
- Composer 2.2.6
- node 14.5.0
- npm 6.14.5
- mysql 8.0.28

時間がない方は、対応済みのものを Github に置いておきますので、下記からどうぞ。
[https://github.com/HajimeKonagai/laravel-breeze-react-ts-sass](https://github.com/HajimeKonagai/laravel-breeze-react-ts-sass)

使い方や、「〜とは」などは、公式や別の方の記事を参照して下さい。
各々パラメーターなどは詳しくは解説していません。

# インストール

## Laravel 本体のインストール
```sh
composer create-project laravel/laravel . "8.*" --prefer-dist
```
僕がインストールしたタイミングでは、バージョン 8.83.1 でした。

## Laravel Breeze + React のインストール

Laravel をインストールしたディレクトリで

```sh
composer require laravel/breeze --dev
```

```sh
php artisan breeze:install react
```
この時点で色々ファイルができます。主に認証関係。
"npm install && npm run dev" って出ますが、後でどちらにしても流すので、この時点ではやらなくてもいいです。


## TypeScript をインストール + tsconfig.json (TypeScript の設定ファイル) を生成
```sh
npm install --save-dev typescript @types/node @types/react @types/react-dom
```
```sh
./node_modules/.bin/tsc --init
```




#【本題】

## 設定ファイルの書き換え

### tsconfig.json
TypeScript の設定ファイルです。

```jsonc
{
  "compilerOptions": {
    "target": "es5",
    "jsx": "react",
    "module": "es2020",
    "moduleResolution": "node",
    "baseUrl": "./",
    "paths": {
      "@/*": ["resources/ts/*"]
    },
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitAny": false,
    "skipLibCheck": true 
  },
  "include": [
      "resources/ts/**/*"
    ],
  "exclude": ["node_modules", "public"]
}

```
### tailwind.config.js
TailwindCss の設定ファイルです

```js
module.exports = {
    content: [
        './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
        './storage/framework/views/*.php',
        './resources/views/**/*.blade.php',
        './resources/ts/**/*.js',  // パスの書き換え
        './resources/ts/**/*.ts',  // 追加
        './resources/ts/**/*.tsx', // 追加
    ],

    theme: {
        extend: {
            fontFamily: {
                sans: ['Nunito', ...defaultTheme.fontFamily.sans],
            },
        },
    },

    plugins: [require('@tailwindcss/forms')],
};
```

### webpack.config.js

```js
const path = require('path');

module.exports = {
    resolve: {
        alias: {
            '@': path.resolve('resources/ts'), // ts に変更
        },
		extensions: [".ts", ".tsx", ".js"] // 解決可能な拡張子として `.ts`と` .tsx`を追加します。
    },
};

```

### webpack.mix.js
```js
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.ts('resources/ts/app.tsx', 'public/js') // mix.js -> mix.ts パスを js ts に、拡張子は tsx に
    .react()
    .sass('resources/sass/app.scss', 'public/css') // sass のトランスパイルを追記
	// postCss は options で
    .options({
        postCss: [
			// postCssの第3引数そのまま
            require('postcss-import'),
            require('tailwindcss'),
            require('autoprefixer'),
        ]
    })
	/* postCss() にそのままsass を渡すとエラーになります
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer'),
    ])
	*/
    .webpackConfig(require('./webpack.config'));

if (mix.inProduction()) {
    mix.version();
}

```

ここがキモでした。
Breeze をインストール直後では poseCss の第3引数にオプションを渡す方式なのですが、
そのままだと sass をトランスパイルさせようとするとエラーが出ます。
最初は import 分のみ css に残して
    ```.sass('resources/sass/app.scss', 'public/css')```
    ```.postCss('resources/css/app.css', 'public/css', [```
    ```    require('postcss-import'),```
    ```    require('tailwindcss'),```
    ```    require('autoprefixer'),```
    ```])```
のようにしていたんですが、これだと tailwindCss の素敵機能 ``` @apply ``` が使えません。


## ディレクトリの変更
- **resources/css/app.css → resources/sass/app.scss に**
- **resources/js → resources/ts に**

ディレクトリの変更は必須ではありませんが、js, css ディレクトリのままやる場合は、後記する設定ファイルの「resources/ts」の箇所は「resources/js」など適宜読み替えてください。

## 拡張子の変更

- **ファイル拡張子を js → ts(tsx) に**

ソースに jsx 記法があるファイルは拡張子 .tsx にします。
なので resources/app.tsx Layouts, Pages にあるファイルは全て .tsx に変更します。
(<font color=red>bootstrap.js は js のまま</font>です。すみません。そこまで拘らなくてもいいかなと。)
<font color=red>※一旦動かすために Components 以下は js で置いておきます。修正内容が多いので別記事で取り上げます。</font>


## 一旦動かしてみる

```sh
npm install && npm run dev
```

してください。
まだこの時点ではエラーが出ます、

``` Additional dependencies must be installed. This will only take a moment.
Running: npm install ts-loader sass-loader@^12.1.0 sass resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
Finished. Please run Mix again.```
って怒られる場合は素直に、Running の後ろ

```sh
npm install ts-loader sass-loader@^12.1.0 sass resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
```
して下さい。

他、エラーが主に2つ出ると思うのですが、
#### ``` TS2304: Cannot find name 'route'. ``` が出ている場合

該当のファイルに

```js
declare var route;
```
を import 文の下、コンポーネント定義(export default 〜)の上あたりに。書いてあげると消えます。
```route``` はおそらく inertiajs が生成する、グローバル変数を参照しているのではないかと。

#### ```TS2322: Type '{ children: Element[]; ...```が出ている場合
シンプルに Dashboard から Authenticated コンポーネントを呼び出す際に、Authenticated の引数にない errors を渡そうとしているのが原因です。Dashboard の 9行目あたりの ```errors={props.errors}``` を消すかコメントアウトすればいいです。


## 動かしてみる
必要な対応は以上でした。

```sh
npm install && npm run dev
```
して ```webpack compiled successfully``` と出れば成功です。



引き続き、
<font color=red>※一旦動かすために Components 以下は js で置いておきます。修正内容が多いので別記事で取り上げます。</font>
の部分頑張ってみます。
(自分でアプリケーション作る時はあんまり必要ないんですけどね)