Produced by Fourier

Laravelライブラリモノリポ開発方法まとめ - 開発編

Hirayama icon Hirayama

前回 の記事では、Laravelライブラリのモノリポ開発の構成を解説し、最低限開発するための環境を整えました。

本記事ではより効率よく開発を行うため、Laravelアプリケーションの開発環境に近づけることを目標に、ライブラリの導入や設定などを行なっていきます。

1. artisanコマンド

通常のLaravelアプリケーションでは php aritsanartisan コマンドを実行しますが、ライブラリ開発で同様のコマンド実行をするには、 orchestra/testbenchvendor/bin/testbench コマンドを使用します。

# アプリケーションでマイグレーションする例
php artisan migrate

# ライブラリ開発でマイグレーションする例
./vendor/bin/testbench migrate

個人的には artsain コマンドは頻繁に実行するので、以下のような artisan というファイル名のPHPファイル(拡張子なし)をリポジトリ直下に置いて、通常のLaravelアプリケーションと同じように実行できるようにすることをお勧めします。

#!/usr/bin/env php
<?php

array_shift($argv);
$command = 'vendor/bin/testbench '. implode(' ', array_map('escapeshellarg', $argv));

if (!in_array('--ansi', $argv, true) && !in_array('--no-ansi', $argv, true)) {
    $command .= ' --ansi';
}

passthru($command, $exitCode);

return $exitCode;
artisan

このファイルは、 artisan コマンドの引数をそのまま testbench に渡し、パススルーで実行結果を表示しています。 --ansi オプションも付与しているので、文字の色や背景色などもそのまま表示されます。

また、 chmod +x artisan を実行して実行権限を付与することで、 ./artisan migrate のように php を付けなくても実行できるようになります。

2. laravel-ide-helperの導入

Laravel開発では、 laravel-ide-helper を導入するとモデルに補完が効くようになって開発がしやすくなりますが、ライブラリ開発では通常とはフォルダ構成が異なるため、モデルをide-helperが認識できるように登録する必要があります。

モデル登録

laravel-ide-helperのConfigには、 ide-helper.model_locations という設定項目があり、そこにモデルが配置されているフォルダを登録することで、認識させることができます。

laravel-ide-helper/config/ide-helper.php at 1fa84a3b65f51891a4663d154d6c692e41b4eeed · barryvdh/laravel-ide-helper thumbnail
laravel-ide-helper/config/ide-helper.php at 1fa84a3b65f51891a4663d154d6c692e41b4eeed · barryvdh/laravel-ide-helper

IDE Helper for Laravel. Contribute to barryvdh/laravel-ide-helper development by creating an account on GitHub.

https://github.com/barryvdh/laravel-ide-helper/blob/1fa84a3b65f51891a4663d154d6c692e41b4eeed/config/ide-helper.php#L131-L146

まずは、以下のように必要なライブラリをインストールします。 symfony/finder はパス登録を楽にするために使用します。

composer require --dev barryvdh/laravel-ide-helper symfony/finder

次に、 workbench/app/Providers/WorkbenchServiceProvider.php ファイルに定義されているServiceProviderを以下のように書き換えます。

<?php

namespace Workbench\App\Providers;

use Illuminate\Support\ServiceProvider;

class WorkbenchServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        if ($this->app->runningInConsole()) {
            $this->setIdeHelperConfig();
        }
    }

    protected function setIdeHelperConfig(): void
    {
        $paths = array_keys(iterator_to_array(
            Finder::create()
                ->directories()
                ->name('Packages')
                ->in(['src/Packages/*'])
                ->getIterator()
        ));
        $this->app['config']->set('ide-helper.model_locations', $paths);
    }
}

このコードのキモとなるのが、 setIdeHelperConfig 関数で、 Findersrc/Packages/* フォルダのパスを一覧取得し、 ide-helper.model_locations にセットすることで、認識させることができます。

設定後は、 php artisan ide-helper:models を実行すると、普通のLaravelアプリケーションのようにPHPDocが生成されます。

3. ブラウザ表示

orchestra/testbench では、 composer serve コマンドを使用することで、Laravelアプリケーションと同様開発サーバーを立ち上げることができます。

また、 testbench.yaml ファイルを作成することで、初期化を実行したり、読み込むServiceProviderを指定することができます。

providers:
  - Laravel\Sanctum\SanctumServiceProvider
  - Barryvdh\Debugbar\ServiceProvider
  - Bit\ClosureTable\ClosureTableServiceProvider
  - Bit\LaravelValidationRules\LaravelValidationRulesServiceProvider
  - Bit\PlaneBlade\Providers\PlaneBladeComponentServiceProvider
  - Bit\UtilKit\Providers\UtilKitServiceProvider
  - App\Providers\WorkbenchServiceProvider
  - App\Providers\WorkbenchRouteServiceProvider

seeders:
  - Workbench\Database\Seeders\DatabaseSeeder

# CLI only environments
env:
  SESSION_CONNECTION: mysql
  CACHE_STORE: database

workbench:
  welcome: false
  install: false
  auth: false
  discovers:
    config: true
  build:
    - migrate:refresh
    - db:seed
    - optimize:clear
    - storage:link

4. Vite

Laravelの Asset Bundling(Vite) でも説明されているように、LaravelではViteを使ってアセットデータをビルドするのが一般的だと思います。

ライブラリ開発でViteを使うのは少々大変ですが、本記事ではSimpleLibを例にその方法を解説します。

ℹ️
今回の設定では、アセットをビルド しない で公開することを前提にセットアップします。TypeScriptやSass等のビルドが必要な言語で実装したコードは、ユーザーが直接使用することになります。 もしビルドする場合は、ビルドしたファイルをgitに 含め 、コミットする必要があります。例えば、 laravel/telescope では dist フォルダにビルド済みファイルを入れており、 telescope:install コマンドでアプリケーションにコピーされます。

モノリポ構成準備とnpmパッケージのインストール

JavaScriptの開発を行うため、まずはセットアップから始めます。

モノリポ構成におけるライブラリマネージャーはyarnかpnpmが選択肢に挙がりますが、個人的にはライブラリのインストールが高速なことや、 Workspace 機能が便利なことから、pnpmがお勧めです。

ℹ️
pnpmのモノリポ構成は以下の記事がとても参考になりました。

まずは、 workbench フォルダと src/Fourier の各パッケージフォルダに、以下のような package.json ファイルを作成します。

{
  "private": true,
  "type": "module"
}

作成後、ファイルは以下のような配置になっているはずです。

.
├── package.json
├── src
│   └── Fourier
│       ├── AwesomeLib
│       │   └── package.json
│       └── SimpleLib
│           └── package.json
└── workbench
    └── package.json

次に、 pnpm-workspace.yaml ファイルでパッケージのパスを記載します。ここでは、 workbenchsrc/Fourier 下の各フォルダがパッケージとして認識されるようにします。

packages:
  - workbench
  - src/Fourier/*

そして、トップから各パッケージのコマンドが実行できるように、 scripts に追記します。

{
  "private": true,
  "type": "module",
  "scripts": {
    "workbench": "pnpm -C workbench",
    "pkg:awesome-lib": "pnpm -C src/Fourier/AwesomeLib",
    "pkg:simple-lib": "pnpm -C src/Fourier/SimpleLib"
  }
}

これらの準備が終わったら、最低限必要なパッケージをworkbenchにインストールします。

pnpm workbench add vite laravel-vite-plugin

vite.config.ts ファイル作成

パッケージのインストール後、 workbench フォルダに vite.config.ts ファイルを作成します。

import laravel from "laravel-vite-plugin";
import fs from "node:fs";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    laravel({
      hotFile: "public/laravel.hot",
      buildDirectory: "../../../../../workbench/public/build",
      input: [
        // 読み込みたいライブラリのファイルパスを記載
      ],
    }),
  ],
});

hotFilebuildDirectory の記載についてですが、これはcomposer devで開発サーバーを起動中、 orchestra/testbench ではプロジェクトのルートが vendor/testbench-core/laravel になるため、通常のLaravelアプリケーションの設定では hot ファイルや build フォルダをVite側で読み込めなくなります。 それを回避するため、 workbench フォルダに public フォルダを作成し、 vite.config.tshotFile には public/laravel.hot とhotファイルを明示的に指定し、 buildDirectory には vendor/testbench-core/laravel からの workbench/public/build の相対パスを指定します。

開発サーバー設定

viteの設定ができたら、開発サーバーを起動するためのコマンドを設定します。

まず、 workbench/package.json にdevコマンドを追加します。

{
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite"
  },
  "dependencies": {
    "laravel-vite-plugin": "^2.0.1",
    "vite": "^7.1.3"
  }
}

次に、 composer.jsondev コマンドを追加し、 composer servepnpm workbench dev を同時に実行できるようにします。

{
    "scripts": {
        "build": "@php vendor/bin/testbench workbench:build --ansi",
        "dev": [
            "Composer\\Config::disableProcessTimeout",
            "npx concurrently -c \"#93c5fd,#fdba74\" \"composer serve\" \"pnpm workbench dev\" --names=server,vite"
        ],
        "serve": [
            "Composer\\Config::disableProcessTimeout",
            "@build",
            "@php vendor/bin/testbench serve --ansi"
        ]
    }
}

これで composer dev を実行すると、viteとLaravelの開発サーバーが同時に立ち上がる、Laravelアプリケーションと同等の動作をするようになります。

ただ、これだけだと hot ファイルと build フォルダの場所が変わったことをLaravel(PHP)側に伝わっておらず、 @vite といったBlade構文を使用するとエラーが発生します。

これを回避するには、Bladeファイルの先頭で Vite ファサードを使用することで解消できます。

@php
    /**
     * The path to the workbench public directory.
     */
    Vite::useHotFile(realpath(__DIR__ . '/../../../../../../../workbench/public/synergy.hot')) // the __DIR__ path is relative to the vendor/orchestral/testbench-core/laravel/storage/framework/views directory
        ->useBuildDirectory("../../../../../workbench/public/build"); // the build directory path is relative to the vendor/orchestral/testbench-core/laravel/public directory
@endphp

5. テストの書き方

ライブラリの開発においてテストを書くことは大事です。 ただ、モノリポ開発だからといってテストの書き方が何か変わるかというとそういうことは無く、各ライブラリごとに通常の開発とほとんど同じようにテストを書くことができます。

6. 依存関係の注意点

モノリポ構成において注意しなければならない点としては、 use 文による他のライブラリコードの利用で依存関係を更新し忘れないようにすることです。 モノリポで use 文を書いた時は正しく動作しますが、リリース後はモノリポ構成ではないので、各パッケージに正しく依存関係を書いていないと必要なライブラリがインストールされず、エラーになります。

そのため、必ず composer.json の内容が必要な依存ライブラリをインストールできているか注意する必要があります。

{
    "require": {
        "illuminate/support": "^12.0",
        "fourier/awesome-lib": "^1.0"
    }
}
依存しているライブラリの依存関係を composer.json に書く

まとめ

本記事では、開発効率を上げるための様々な方法を取り上げ、Laravelアプリケーションと同じように開発できるための方法を解説しました。

今回解説した内容は前回同様リポジトリに公開しているので、参考になればと思います。

GitHub - FOURIER-Inc/laravel-example-monorepo thumbnail
GitHub - FOURIER-Inc/laravel-example-monorepo

Contribute to FOURIER-Inc/laravel-example-monorepo development by creating an account on GitHub.

https://github.com/FOURIER-Inc/laravel-example-monorepo

GitHub - FOURIER-Inc/awesome-lib thumbnail
GitHub - FOURIER-Inc/awesome-lib

Contribute to FOURIER-Inc/awesome-lib development by creating an account on GitHub.

https://github.com/FOURIER-Inc/awesome-lib

GitHub - FOURIER-Inc/sample-lib thumbnail
GitHub - FOURIER-Inc/sample-lib

Contribute to FOURIER-Inc/sample-lib development by creating an account on GitHub.

https://github.com/FOURIER-Inc/sample-lib

まだ書き切れてないことも多く、実装方法などには触れていませんでしたので、ライブラリ開発において自分が参考にしたサイトをご紹介して、本記事を締めたいと思います。

参考サイト

LaravelPackage.com

Laravelのライブラリ開発を解説しているサイトです。

恐らく有志の方が作成したサイトだと思いますが、実装機能ごとに細かい設定やサンプル実装、テスト方法まで網羅されており、Laravelライブラリにおいて有用な情報が数多く掲載されていたため、作り始めたばかりのころはとても参考にしていました。

Test Bench

orchestra/testbench のドキュメントサイトです。

testbenchはライブラリ開発のベースになるので、特にテストを書く際はこのドキュメントサイトをよく確認した方が良いです。

Hirayama icon

Hirayama slash forward icon Engineer

業務では主にPHPやTypeScriptを使用したバックエンドアプリケーションやデスクトップアプリケーションの開発をしています。趣味は登山。