Laravel8 laravel-mix で Typescript + Vue3 +  でアプリケーションを作成

`laravel/ui` で生成した標準のScaffoldが使用できず、調べてもバージョンによる違いがあったり、手順が散り散りなので必要な設定をプロジェクト作成からまとめておく。

いっぺんに導入するとどこでミスってるかわからないので一つずつ確認しながら導入していく。

----

# 手順

## プロジェクトの作成

```bash
$ laravel new app
```

appは任意のアプリケーション名。
laravelコマンドは composerを使ってグローバルインストールしておく。

作成後はプロジェクトルートに移動して依存ライブラリをインストールしておく。

```bash
$ cd ./app
$ composer install
$ npm install
```

---

## Typescriptの導入

上記で作成したプロジェクトのフロントはjavascriptなのでtypescriptのプロジェクトに変更する。

ソースを配置するディレクトリを作成

```bash
$ mkdir -p ./resources/ts
```

app.ts を作成

```./resources/ts/app.ts
console.log("hello")
```

laravel-mixの設定をtsに変更する。

```./webpack.mix.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.ts', 'public/js/app.js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]);
```

この状態でビルドしようとすると、必要なパッケージが表示されるのでインストールする。

```bash
$ npm run dev
...
> development
> mix

        Additional dependencies must be installed. This will only take a moment.

        Running: npm install ts-loader typescript --save-dev --legacy-peer-deps
```

```bash
$ npm install ts-loader typescript --save-dev --legacy-peer-deps
```

tsconfigを生成

```bash
$ npx tsc --init
```

ビルドできることを確認する

```bash
$ npm run dev
```

ビルドに成功したらwelcomeページでスクリプトを読み込んで実行されることを確認する。
headかbodyの中に以下の1行を追記する。もともと書いてるheadやbodyの内容は必要ないものは削除してOK。

```welcome.blade.php
<script src="/js/app.js"></script>
```

この状態で、サーバを起動してアクセスするとコンソールにメッセージが出力される。

```bash
$ php artisan serve
```

もともとあったjsのディレクトリは削除してOK。

---

## Vue3の導入

Vue3をインストールしてAppコンポーネントをbladeのviewにマウントする。
ちなみに、現時点でVuetifyはVue3に対応してないので、Vuetifyを使用したいのであればVue2を使うことをおすすめする。

導入したいVueのバージョンを指定してプロジェクトにインストールする。
現時点で再審をインストールすると、 `vue@3.2.37` がインストールされる。

```bash
$ npm install -D vue
```

インストール後に、laravel-mixの設定でvueを読み込む。

```webpack.mix.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.ts', 'public/js/app.js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ])
    .vue(); // ここを追記
```

この状態でビルドするとvue-loaderを入れるように言われるのでインストール。

```bash
$ npm run dev
...
> development
> mix

        Additional dependencies must be installed. This will only take a moment.

        Running: npm install vue-loader@^16.2.0 --save-dev --legacy-peer-deps
```

```bash
$ npm install vue-loader@^16.2.0 --save-dev --legacy-peer-deps
```

ビルドできることを確認する。

```bash
$ npm run dev
```

vueファイルをコンポーネントとして扱えるように設定ファイルを追加。

```bash
$ mkdir -p ./resources/ts/@types
```

```./resources/ts/@types/shim-vue.d.ts
declare module "*.vue" {
    import type { DefineComponent } from "vue";
    const component: DefineComponent<{}, {}, any>;
    export default component;
}
```

Appコンポーネントを作成

```bash
$ mkdir -p ./resources/ts/components
```

```./resources/ts/components/App.vue
<template>
  <h1>Hello</h1>
</template>
<script>
import { defineComponent } from "vue"

export default defineComponent({
  components: {},
});
</script>
```

Appコンポーネントを読み込む。

```./resources/ts/app.ts
import { createApp } from "vue"
import App from "./components/App.vue";

const app = createApp(App);
app.mount("#app");
```

viewにマウントポイントを配置。
app.jsは `defer` をつけて遅延ロードする。

```welcome.blade.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>Laravel</title>

        <!-- Fonts -->

        <script src="/js/app.js" defer></script>

        <!-- Styles -->

    </head>
    <body class="antialiased">
        <div id="app"></div>
    </body>
</html>
```

この状態でサーバを起動してアクセスするとAppコンポーネントの内容が表示される。

---

mix向けの設定はこれくらい。
あとは、適宜tsにコンポーネントやページ、php側にAPIを実装したりする。