Laravel+Vue.js+Typescript環境構築手順

##環境
Laravel Framework 8.58.0
npm version
{
  npm: '7.20.1',
  node: '15.12.0',
  v8: '8.6.395.17-node.27',
  uv: '1.41.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.17.1',
  modules: '88',
  nghttp2: '1.42.0',
  napi: '8',
  llhttp: '2.1.3',
  openssl: '1.1.1j+quic',
  cldr: '38.1',
  icu: '68.2',
  tz: '2020d',
  unicode: '13.0'
}


###Laravelプロジェクト作成
まず、Laravelのプロジェクトを作成
composer create-project --prefer-dist laravel/laravel プロジェクト名

###laravel/uiインストール
laravel/uiパッケージをcomposerでインストール。

下記コマンドを実行。
```composer require laravel/ui```

###laravel/ui vueインストール
```php artisan ui vue```
このコマンドで、package.jsonにフロントエンドのパッケージが追加されたり、
ベースのjsファイルやサンプルのVueコンポーネント、
Laravel Mixの設定ファイルなどが配置される。

###npmインストール
```npm install```

ここまででLaravelにVueを使えるようにできました！
次はVueをTS化していきましょう

##TypeScript化
###tsconfig.jsonを追加
tsconfig.jsonファイルをwork配下に作成
ファイルの中身は以下
```{
  "compilerOptions": {
    "outDir": "./built/",
    "sourceMap": true,
    "strict": true,
    "noImplicitReturns": true,
    "noImplicitAny": true,
    "module": "es2015",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "target": "es5",
    "lib": [
      "es2016",
      "dom"
    ]
  },
  "include": [
    "resources/assets/ts/**/*"
  ]
}```
###vue.shims.d.tsファイル作成
vue.shims.d.tsファイルをcomponents配下に作成
中身は以下を記述
```declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}```
###webpack.mix.jsを編集
webpack.mix.jsファイルに以下を記述
```const mix = require('laravel-mix');
mix.ts('resources/assets/ts/app.ts', 'public/js').vue()
  .sass('resources/assets/sass/app.scss', 'public/css');```
###package.json(scripts内のパスのみ修正)
中身を以下に編集
```{
    "private": true,
    "scripts": {
        "dev": "node node_modules/cross-env/src/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "node node_modules/cross-env/src/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch-poll": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "hot": "node node_modules/cross-env/src/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "production": "node node_modules/cross-env/src/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "cross-env": "^7.0",
        "laravel-mix": "^5.0.1",
        "lodash": "^4.17.13",
        "resolve-url-loader": "^3.1.0",
        "sass": "^1.15.2",
        "sass-loader": "^8.0.0",
        "ts-loader": "^6.2.1",
        "typescript": "^3.8.3",
        "vue": "^2.6.11",
        "vue-property-decorator": "^8.4.1",
        "vue-template-compiler": "^2.6.11"
    },
    "dependencies": {
        "webpack": "^4.42.0"
    }
}```
###resources/views/welcome.blade.phpの中身を編集
以下にファイルの中身を編集
```<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="csrf-token" content="{{ csrf_token() }}">
  <title>Laravel</title>
  <link rel="stylesheet" href="/css/app.css">
</head>
<body>
<main>
  <div id="app"></div>
</main>
<script src="/js/app.js"></script>
</body>
</html>```
###resources/js/app.jsを変更
resources/js/app.jsをresources/ts/app.tsに変更し、中身を以下に編集
```import Vue from 'vue';
import bootstrap from './bootstrap';
import AppComponent from './components/App.vue';

bootstrap();

window.Vue = require("vue").default;

const app = new Vue({
  el: '#app',
  render: h => h(AppComponent)
});```
###resources/js/bootstrap.jsを変更
resources/js/bootstrap.jsをresources/ts/bootstrap.tsに変更し、中身を以下に編集
```import Axios, { AxiosStatic } from 'axios';
declare global {
  interface Window {
    axios: AxiosStatic;
  }
  interface Element {
    content: string;
  }
}
export default function bootstrap() {
  window.axios = Axios;
  window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
  let token = document.head.querySelector('meta[name="csrf-token"]');
  if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
  } else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
  }
}```
###resources/ts/components/App.vueの変更
resources/ts/components/App.vueファイルの中身を以下に編集
```<template>
  <div class="App">
    <div class="container">
      <div class="row">
        <div class="col-md-8 col-md-offset-2">
          <h1>{{ message }}</h1>
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
  import { Vue, Component } from 'vue-property-decorator';
  @Component
  export default class App extends Vue {
    message = 'Laravel + Vue.js + TypeScript';
  }
</script>
<style scoped>
  h1 {
    text-align: center;
    margin: 4rem 0;
  }
</style>```
###--hide-modulesのエラー
ここまでで以下のコマンドを実行すると、以下のエラーが表示されるはず
```error: unknown option ‘--hide-modules’ [webpack-cli] Run ‘webpack --help’```
vs codeで```--hide-modules```を検索します。
該当箇所を削除すれば解消されます。