Laravel9 + Vue.js3 + Inertia.js + TypeScript (+ Vuetify)をDockerで環境構築

Laravel9だとBreezeを使ってTypeScriptが選択できません。手動で行う必要があります。
初期設定でTypeScriptを選択したければ、Laravel10とBreezeで開発を進めましょう。

今回はLaravel9でのTypeScript環境を作るための備忘録です。

Docker設定

project-root/
├── docker/
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       ├── Dockerfile
│       └── php.ini
├── src/
│   └── laravel
├── docker-compose.yml

以上のディレクトリ構成で。
src配下にLaravelプロジェクトがインストールされるので、わかりやすくディレクトリ名を変えても可。
変えた場合はdocker-compose.ymlのvolumesも変える。

server {
    listen 80;
    index index.php index.html index.htm;

    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        # FastCGIの設定をここに直接記述
        fastcgi_pass app:9000;  # PHPサービスへのリンク
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # 必要なFastCGIパラメータをここに定義
        include fastcgi_params;  # 他のFastCGIパラメータを読み込む
    }

    location ~ /\.ht {
        deny all;
    }
}

1. default.confを作成

FROM php:8.3-fpm

# 必要なPHP拡張機能をインストール
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libzip-dev \
    unzip \
    git \
    curl && \
    docker-php-ext-configure gd --with-freetype --with-jpeg && \
    docker-php-ext-install gd zip pdo pdo_mysql

# 作業ディレクトリを設定
WORKDIR /var/www/html

# Composerをインストール
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# php.ini設定ファイルをコピー
COPY php.ini /usr/local/etc/php/conf.d/custom.ini

# Node.jsとnpmをインストール(Node.js 20.xを使用)
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
    apt-get install -y nodejs && \
    npm install -g npm@latest

# 権限の設定(必要に応じて)
RUN chown -R www-data:www-data /var/www/html

# Laravel用エントリーポイント
CMD ["php-fpm"]

2. Dockerfileを作成

; 日付設定
[Date]
date.timezone = "Asia/Tokyo"
; 文字&言語設定
[mbstring]
mbstring.language = "Japanese"

3. php.iniを作成

services:
  app:
    image: php:8.2-fpm
    ports:
      - "5173:5173"
    build:
      context: ./docker/php
    container_name: app
    volumes:
      - ./src/laravel:/var/www/html
    depends_on:
      - db
    networks:
      - app-network

  web:
    image: nginx:alpine
    container_name: nginx
    volumes:
      - ./src/laravel:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "8080:80"
    networks:
      - app-network
    depends_on:
      - db


  db:
    image: mysql:8
    container_name: mysql_db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - app-network

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "8081:80"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  db_data:
    driver: local

4. docker-compose.ymlを作成
portsやcontainer_nameは競合しないように環境によって都度変える

docker compose up -d —build

5. dockerを立ち上げる

docker compose exec app bash
composer create-project --prefer-dist laravel/laravel . "9.*"

6. コンテナ内に入り、Laravelセットアップ
以降、インストール関連は全てコンテナ内で行う

Laravel関連

1.localhost:8080localhost:8081へアクセスし、確認する

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:fn0GiuZN/2UTrhg40/dTsg8gHO/GuU+jIJxDAJ3S5MI=
APP_DEBUG=true
APP_URL=http://localhost:8080

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=user
DB_PASSWORD=password

2. .envを修正
APP_URLと、DB関連。docker-compose.ymlのdbで設定した内容に変更する

php artisan migrate

3. マイグレーションを行う

4. phpMyAdminへアクセスし、テーブル確認

'timezone' => 'Asia/Tokyo', 

'locale' => 'ja',

5. config/app.phpのタイムゾーンを変更する

6. langファイル作成
https://github.com/snowleaf-com/sekkotuin_crm/tree/main/src/sekkotuin/lang/ja
上記より4つのファイルをコピーし、lang/jaディレクトリを作成し追加

composer require barryvdh/laravel-debugbar --dev

7. デバッグバーインストール

composer require laravel/breeze:^1 --dev

php artisan breeze:install vue

8. LaravelBreeze(Laravel9はBreeze2をインストールできない)インストール

server: {
    host: '0.0.0.0',
    watch: {
        usePolling: true,
    },
    port:5173,
}

9. vite.config.jsに以上を追記

composer require inertiajs/inertia-laravel

10. Inertia.jsインストール

php artisan inertia:middleware 

11. Inertiaのミドルウェア作成
Laravel側でInertia.jsが正しく動作し、クライアントサイド(Vue.js)とのやりとりをスムーズにするための準備

\App\Http\Middleware\HandleInertiaRequests::class,

12. /app/Http/Kernel.phpへ以上を追記(webの中)

“@inertiajs/inertia”: “^0.11.0”,
“@inertiajs/inertia-vue3”: “^0.6.0”,

13. package.jsonのdevDependensicesに以上を追記(inertia1の書き方)

npm install

14. 追記したら以上のコマンド

npm install vuetify@next

16. vuetify3インストール

TypeScript関連

npm install vue-tsc --dev

1. vue-tscインストール(型チェック)

npx tsc --init

2. tsconfig.jsonを作成する

{
    "compilerOptions": {
        "allowJs": true,
        "module": "ESNext",
        "moduleResolution": "bundler",
        "jsx": "preserve",
        "strict": true,
        "isolatedModules": true,
        "target": "ESNext",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "skipLibCheck": true,
        "paths": {
            "@/*": ["./resources/js/*"],
            "ziggy-js": ["./vendor/tightenco/ziggy"]
        },
    },
    "include": ["resources/js/**/*.ts", "resources/js/**/*.d.ts", "resources/js/**/*.vue"]
}

3. tsconfig.jsonを以上のように修正する

"scripts": {
    "dev": "vite",
    "build": "vite build",
    "type:check": "vue-tsc --noEmit"
},

4. package.jsonに型チェック用のコマンド追記
—noEmitでトランスパイルせずに型チェックのみ行う

npm run type:check

5. 以上のコマンドで型チェックできる

import './bootstrap';
import '../css/app.css';

import { createApp, h, DefineComponent } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';

import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import 'vuetify/styles';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob<DefineComponent>('./Pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        const vuetify = createVuetify({ components, directives });
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ZiggyVue)
            .use(vuetify)
            .mount(el);
    },
    progress: {
        color: '#4B5563',
    },
});

6. resources/js/app.jsをapp.tsに変え、以上のように修正する
vuetifyが不要な場合は9行目〜12行目、21行目、24行目を消す

@vite(['resources/js/app.ts', "resources/js/Pages/{$page['component']}.vue"])

7. resources/views/app.blade.phpの@viteのapp.jsをapp.tsへ修正

input: 'resources/js/app.ts',

8. vite.config.jsもvite.config.tsへ変更し、inputのapp.jsをapp.tsへ修正

import _ from 'lodash';
window._ = _;

9. bootstrap.jsもbootstrap.tsへ変更し、上記の1行目、2行目を削除する

import { PageProps as InertiaPageProps } from '@inertiajs/core';
import { AxiosInstance } from 'axios';
import { route as ziggyRoute } from 'ziggy-js';
import { PageProps as AppPageProps } from './';

declare global {
    interface Window {
        axios: AxiosInstance;
    }

    var route: typeof ziggyRoute;
}

declare module 'vue' {
    interface ComponentCustomProperties {
        route: typeof ziggyRoute;
    }
}

declare module '@inertiajs/core' {
    interface PageProps extends InertiaPageProps, AppPageProps {}
}

10. resources/js/にtypesディレクトリを作り、その中にglobal.d.tsを作成し以上を記述

export interface User {
    id: number;
    name: string;
    email: string;
    email_verified_at: string;
}

export type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
    auth: {
        user: User;
    };
};

11. resources/js/typesディレクトリの中にindex.d.tsを作成し以上を記述

/// <reference types="vite/client" />

12. resources/js/typesディレクトリの中にvite-env.d.tsを作成し以上を記述

確認作業

<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        \App\Models\User::factory(10)->create();

        \App\Models\User::factory()->create([
            'name' => 'Test User',
            'email' => 'test@test.com',
        ]);
    }
}

1.database/seeders/DatabaseSeeder.phpを上記のように編集
nameとemailは好きなように

php artisan db:seed

2.シーディングコマンドでテストユーザー作成

npm run dev

3.viteを起動させ、実際にログインして、Profile画面などに遷移してみて異常がなければOK