スマレジのテックファーム(SES 部門)で Web 系エンジニアとして働いている やまて(@r_yamate) と申します。
2023 年 4 月からは、スマレジの関連アプリの開発業務を担当しています。触ったことのなかった Flutter での開発を担当(React も少々)することになり、日々奮闘中です。開発しているアプリはモニター利用も始まり、開発の醍醐味を味わえていて楽しいです。
はじめに
今回は、Laravel 10 と React 18 を使用した SPA 開発環境を Laravel Sail を活用して構築手順について、ハンズオンの記録をまとめます。
以下の記事を参考にさせていただき、ハンズオンで実行した記録です。
目次
開発環境
- macOS Monterey 12.6.5 (MacBook Pro 2016)
- Docker 20.10.8
バックエンド
- Laravel 10(Laravel Sail, Vite)
- MySQL 8
フロントエンド
- React 18
- Sass
- TypeScript
Laravel Sail とは
Laravel Sail は Docker ベースの開発環境を簡単に構築できるツールです。
1. Laravel の開発環境構築
Laravel の開発環境を構築します。
※ Docker Desktop が必要です。
1-1. 新規 Laravel プロジェクトの作成
以下のコマンドで、新規プロジェクトを作成します。
curl -s "https://laravel.build/sample-app?with=mysql" | bash
コマンド実行時ログ
# r_yamate @ srC02T54QWH03M in ~/development [18:14:43] $ curl -s "https://laravel.build/sample-app?with=mysql" | bash latest: Pulling from laravelsail/php82-composer Digest: sha256:37549f980be6146efcb16b0dc352644edfc5cca32b9862494631eb197ef89737 Status: Image is up to date for laravelsail/php82-composer:latest _ _ | | | | | | __ _ _ __ __ ___ _____| | | | / _` | '__/ _` \ \ / / _ \ | | |___| (_| | | | (_| |\ V / __/ | |______\__,_|_| \__,_| \_/ \___|_| WARN TTY mode requires /dev/tty to be read/writable. Creating a "laravel/laravel" project at "./sample-app" Installing laravel/laravel (v10.2.9) - Downloading laravel/laravel (v10.2.9) - Installing laravel/laravel (v10.2.9): Extracting archive Created project in /opt/sample-app > @php -r "file_exists('.env') || copy('.env.example', '.env');" Loading composer repositories with package information Updating dependencies Lock file operations: 110 installs, 0 updates, 0 removals - Locking brick/math (0.11.0) - Locking dflydev/dot-access-data (v3.0.2) - Locking doctrine/inflector (2.0.8) - Locking doctrine/lexer (3.0.0) - Locking dragonmantank/cron-expression (v3.3.3) - Locking egulias/email-validator (4.0.2) - Locking fakerphp/faker (v1.23.0) - Locking filp/whoops (2.15.4) - Locking fruitcake/php-cors (v1.3.0) - Locking graham-campbell/result-type (v1.1.2) - Locking guzzlehttp/guzzle (7.8.0) - Locking guzzlehttp/promises (2.0.1) - Locking guzzlehttp/psr7 (2.6.1) - Locking guzzlehttp/uri-template (v1.0.2) - Locking hamcrest/hamcrest-php (v2.0.1) - Locking laravel/framework (v10.32.1) - Locking laravel/pint (v1.13.6) - Locking laravel/prompts (v0.1.13) - Locking laravel/sail (v1.26.0) - Locking laravel/sanctum (v3.3.2) - Locking laravel/serializable-closure (v1.3.3) - Locking laravel/tinker (v2.8.2) - Locking league/commonmark (2.4.1) - Locking league/config (v1.2.0) - Locking league/flysystem (3.21.0) - Locking league/flysystem-local (3.21.0) - Locking league/mime-type-detection (1.14.0) - Locking mockery/mockery (1.6.6) - Locking monolog/monolog (3.5.0) - Locking myclabs/deep-copy (1.11.1) - Locking nesbot/carbon (2.71.0) - Locking nette/schema (v1.2.5) - Locking nette/utils (v4.0.3) - Locking nikic/php-parser (v4.17.1) - Locking nunomaduro/collision (v7.10.0) - Locking nunomaduro/termwind (v1.15.1) - Locking phar-io/manifest (2.0.3) - Locking phar-io/version (3.2.1) - Locking phpoption/phpoption (1.9.2) - Locking phpunit/php-code-coverage (10.1.8) - Locking phpunit/php-file-iterator (4.1.0) - Locking phpunit/php-invoker (4.0.0) - Locking phpunit/php-text-template (3.0.1) - Locking phpunit/php-timer (6.0.0) - Locking phpunit/phpunit (10.4.2) - Locking psr/clock (1.0.0) - Locking psr/container (2.0.2) - Locking psr/event-dispatcher (1.0.0) - Locking psr/http-client (1.0.3) - Locking psr/http-factory (1.0.2) - Locking psr/http-message (2.0) - Locking psr/log (3.0.0) - Locking psr/simple-cache (3.0.0) - Locking psy/psysh (v0.11.22) - Locking ralouphie/getallheaders (3.0.3) - Locking ramsey/collection (2.0.0) - Locking ramsey/uuid (4.7.5) - Locking sebastian/cli-parser (2.0.0) - Locking sebastian/code-unit (2.0.0) - Locking sebastian/code-unit-reverse-lookup (3.0.0) - Locking sebastian/comparator (5.0.1) - Locking sebastian/complexity (3.1.0) - Locking sebastian/diff (5.0.3) - Locking sebastian/environment (6.0.1) - Locking sebastian/exporter (5.1.1) - Locking sebastian/global-state (6.0.1) - Locking sebastian/lines-of-code (2.0.1) - Locking sebastian/object-enumerator (5.0.0) - Locking sebastian/object-reflector (3.0.0) - Locking sebastian/recursion-context (5.0.0) - Locking sebastian/type (4.0.0) - Locking sebastian/version (4.0.1) - Locking spatie/backtrace (1.5.3) - Locking spatie/flare-client-php (1.4.3) - Locking spatie/ignition (1.11.3) - Locking spatie/laravel-ignition (2.3.1) - Locking symfony/console (v6.3.8) - Locking symfony/css-selector (v6.3.2) - Locking symfony/deprecation-contracts (v3.4.0) - Locking symfony/error-handler (v6.3.5) - Locking symfony/event-dispatcher (v6.3.2) - Locking symfony/event-dispatcher-contracts (v3.4.0) - Locking symfony/finder (v6.3.5) - Locking symfony/http-foundation (v6.3.8) - Locking symfony/http-kernel (v6.3.8) - Locking symfony/mailer (v6.3.5) - Locking symfony/mime (v6.3.5) - Locking symfony/polyfill-ctype (v1.28.0) - Locking symfony/polyfill-intl-grapheme (v1.28.0) - Locking symfony/polyfill-intl-idn (v1.28.0) - Locking symfony/polyfill-intl-normalizer (v1.28.0) - Locking symfony/polyfill-mbstring (v1.28.0) - Locking symfony/polyfill-php72 (v1.28.0) - Locking symfony/polyfill-php80 (v1.28.0) - Locking symfony/polyfill-php83 (v1.28.0) - Locking symfony/polyfill-uuid (v1.28.0) - Locking symfony/process (v6.3.4) - Locking symfony/routing (v6.3.5) - Locking symfony/service-contracts (v3.4.0) - Locking symfony/string (v6.3.8) - Locking symfony/translation (v6.3.7) - Locking symfony/translation-contracts (v3.4.0) - Locking symfony/uid (v6.3.8) - Locking symfony/var-dumper (v6.3.8) - Locking symfony/yaml (v6.3.8) - Locking theseer/tokenizer (1.2.2) - Locking tijsverkoyen/css-to-inline-styles (2.2.6) - Locking vlucas/phpdotenv (v5.6.0) - Locking voku/portable-ascii (2.0.1) - Locking webmozart/assert (1.11.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 110 installs, 0 updates, 0 removals - Downloading doctrine/inflector (2.0.8) - Downloading doctrine/lexer (3.0.0) - Downloading symfony/polyfill-ctype (v1.28.0) - Downloading webmozart/assert (1.11.0) - Downloading dragonmantank/cron-expression (v3.3.3) - Downloading symfony/deprecation-contracts (v3.4.0) - Downloading fakerphp/faker (v1.23.0) - Downloading symfony/polyfill-php80 (v1.28.0) - Downloading symfony/polyfill-php83 (v1.28.0) - Downloading symfony/polyfill-mbstring (v1.28.0) - Downloading symfony/http-foundation (v6.3.8) - Downloading fruitcake/php-cors (v1.3.0) - Downloading psr/http-message (2.0) - Downloading psr/http-client (1.0.3) - Downloading ralouphie/getallheaders (3.0.3) - Downloading psr/http-factory (1.0.2) - Downloading guzzlehttp/psr7 (2.6.1) - Downloading guzzlehttp/promises (2.0.1) - Downloading guzzlehttp/guzzle (7.8.0) - Downloading guzzlehttp/uri-template (v1.0.2) - Downloading laravel/pint (v1.13.6) - Downloading symfony/polyfill-intl-normalizer (v1.28.0) - Downloading symfony/polyfill-intl-grapheme (v1.28.0) - Downloading symfony/string (v6.3.8) - Downloading symfony/service-contracts (v3.4.0) - Downloading symfony/console (v6.3.8) - Downloading voku/portable-ascii (2.0.1) - Downloading phpoption/phpoption (1.9.2) - Downloading graham-campbell/result-type (v1.1.2) - Downloading vlucas/phpdotenv (v5.6.0) - Downloading symfony/css-selector (v6.3.2) - Downloading tijsverkoyen/css-to-inline-styles (2.2.6) - Downloading symfony/var-dumper (v6.3.8) - Downloading symfony/polyfill-uuid (v1.28.0) - Downloading symfony/uid (v6.3.8) - Downloading symfony/routing (v6.3.5) - Downloading symfony/process (v6.3.4) - Downloading symfony/polyfill-php72 (v1.28.0) - Downloading symfony/polyfill-intl-idn (v1.28.0) - Downloading symfony/mime (v6.3.5) - Downloading psr/event-dispatcher (1.0.0) - Downloading symfony/event-dispatcher-contracts (v3.4.0) - Downloading symfony/event-dispatcher (v6.3.2) - Downloading psr/log (3.0.0) - Downloading egulias/email-validator (4.0.2) - Downloading symfony/mailer (v6.3.5) - Downloading symfony/error-handler (v6.3.5) - Downloading symfony/http-kernel (v6.3.8) - Downloading symfony/finder (v6.3.5) - Downloading ramsey/collection (2.0.0) - Downloading brick/math (0.11.0) - Downloading ramsey/uuid (4.7.5) - Downloading psr/simple-cache (3.0.0) - Downloading nunomaduro/termwind (v1.15.1) - Downloading symfony/translation-contracts (v3.4.0) - Downloading symfony/translation (v6.3.7) - Downloading psr/clock (1.0.0) - Downloading nesbot/carbon (2.71.0) - Downloading monolog/monolog (3.5.0) - Downloading league/mime-type-detection (1.14.0) - Downloading league/flysystem (3.21.0) - Downloading league/flysystem-local (3.21.0) - Downloading nette/utils (v4.0.3) - Downloading nette/schema (v1.2.5) - Downloading dflydev/dot-access-data (v3.0.2) - Downloading league/config (v1.2.0) - Downloading league/commonmark (2.4.1) - Downloading laravel/serializable-closure (v1.3.3) - Downloading laravel/prompts (v0.1.13) - Downloading laravel/framework (v10.32.1) - Downloading symfony/yaml (v6.3.8) - Downloading laravel/sail (v1.26.0) - Downloading laravel/sanctum (v3.3.2) - Downloading nikic/php-parser (v4.17.1) - Downloading psy/psysh (v0.11.22) - Downloading laravel/tinker (v2.8.2) - Downloading hamcrest/hamcrest-php (v2.0.1) - Downloading mockery/mockery (1.6.6) - Downloading filp/whoops (2.15.4) - Downloading nunomaduro/collision (v7.10.0) - Downloading sebastian/version (4.0.1) - Downloading sebastian/type (4.0.0) - Downloading sebastian/recursion-context (5.0.0) - Downloading sebastian/object-reflector (3.0.0) - Downloading sebastian/object-enumerator (5.0.0) - Downloading sebastian/global-state (6.0.1) - Downloading sebastian/exporter (5.1.1) - Downloading sebastian/environment (6.0.1) - Downloading sebastian/diff (5.0.3) - Downloading sebastian/comparator (5.0.1) - Downloading sebastian/code-unit (2.0.0) - Downloading sebastian/cli-parser (2.0.0) - Downloading phpunit/php-timer (6.0.0) - Downloading phpunit/php-text-template (3.0.1) - Downloading phpunit/php-invoker (4.0.0) - Downloading phpunit/php-file-iterator (4.1.0) - Downloading theseer/tokenizer (1.2.2) - Downloading sebastian/lines-of-code (2.0.1) - Downloading sebastian/complexity (3.1.0) - Downloading sebastian/code-unit-reverse-lookup (3.0.0) - Downloading phpunit/php-code-coverage (10.1.8) - Downloading myclabs/deep-copy (1.11.1) - Downloading phpunit/phpunit (10.4.2) - Downloading spatie/backtrace (1.5.3) - Downloading spatie/flare-client-php (1.4.3) - Downloading spatie/ignition (1.11.3) - Downloading spatie/laravel-ignition (2.3.1) - Installing doctrine/inflector (2.0.8): Extracting archive - Installing doctrine/lexer (3.0.0): Extracting archive - Installing symfony/polyfill-ctype (v1.28.0): Extracting archive - Installing webmozart/assert (1.11.0): Extracting archive - Installing dragonmantank/cron-expression (v3.3.3): Extracting archive - Installing symfony/deprecation-contracts (v3.4.0): Extracting archive - Installing psr/container (2.0.2): Extracting archive - Installing fakerphp/faker (v1.23.0): Extracting archive - Installing symfony/polyfill-php80 (v1.28.0): Extracting archive - Installing symfony/polyfill-php83 (v1.28.0): Extracting archive - Installing symfony/polyfill-mbstring (v1.28.0): Extracting archive - Installing symfony/http-foundation (v6.3.8): Extracting archive - Installing fruitcake/php-cors (v1.3.0): Extracting archive - Installing psr/http-message (2.0): Extracting archive - Installing psr/http-client (1.0.3): Extracting archive - Installing ralouphie/getallheaders (3.0.3): Extracting archive - Installing psr/http-factory (1.0.2): Extracting archive - Installing guzzlehttp/psr7 (2.6.1): Extracting archive - Installing guzzlehttp/promises (2.0.1): Extracting archive - Installing guzzlehttp/guzzle (7.8.0): Extracting archive - Installing guzzlehttp/uri-template (v1.0.2): Extracting archive - Installing laravel/pint (v1.13.6): Extracting archive - Installing symfony/polyfill-intl-normalizer (v1.28.0): Extracting archive - Installing symfony/polyfill-intl-grapheme (v1.28.0): Extracting archive - Installing symfony/string (v6.3.8): Extracting archive - Installing symfony/service-contracts (v3.4.0): Extracting archive - Installing symfony/console (v6.3.8): Extracting archive - Installing voku/portable-ascii (2.0.1): Extracting archive - Installing phpoption/phpoption (1.9.2): Extracting archive - Installing graham-campbell/result-type (v1.1.2): Extracting archive - Installing vlucas/phpdotenv (v5.6.0): Extracting archive - Installing symfony/css-selector (v6.3.2): Extracting archive - Installing tijsverkoyen/css-to-inline-styles (2.2.6): Extracting archive - Installing symfony/var-dumper (v6.3.8): Extracting archive - Installing symfony/polyfill-uuid (v1.28.0): Extracting archive - Installing symfony/uid (v6.3.8): Extracting archive - Installing symfony/routing (v6.3.5): Extracting archive - Installing symfony/process (v6.3.4): Extracting archive - Installing symfony/polyfill-php72 (v1.28.0): Extracting archive - Installing symfony/polyfill-intl-idn (v1.28.0): Extracting archive - Installing symfony/mime (v6.3.5): Extracting archive - Installing psr/event-dispatcher (1.0.0): Extracting archive - Installing symfony/event-dispatcher-contracts (v3.4.0): Extracting archive - Installing symfony/event-dispatcher (v6.3.2): Extracting archive - Installing psr/log (3.0.0): Extracting archive - Installing egulias/email-validator (4.0.2): Extracting archive - Installing symfony/mailer (v6.3.5): Extracting archive - Installing symfony/error-handler (v6.3.5): Extracting archive - Installing symfony/http-kernel (v6.3.8): Extracting archive - Installing symfony/finder (v6.3.5): Extracting archive - Installing ramsey/collection (2.0.0): Extracting archive - Installing brick/math (0.11.0): Extracting archive - Installing ramsey/uuid (4.7.5): Extracting archive - Installing psr/simple-cache (3.0.0): Extracting archive - Installing nunomaduro/termwind (v1.15.1): Extracting archive - Installing symfony/translation-contracts (v3.4.0): Extracting archive - Installing symfony/translation (v6.3.7): Extracting archive - Installing psr/clock (1.0.0): Extracting archive - Installing nesbot/carbon (2.71.0): Extracting archive - Installing monolog/monolog (3.5.0): Extracting archive - Installing league/mime-type-detection (1.14.0): Extracting archive - Installing league/flysystem (3.21.0): Extracting archive - Installing league/flysystem-local (3.21.0): Extracting archive - Installing nette/utils (v4.0.3): Extracting archive - Installing nette/schema (v1.2.5): Extracting archive - Installing dflydev/dot-access-data (v3.0.2): Extracting archive - Installing league/config (v1.2.0): Extracting archive - Installing league/commonmark (2.4.1): Extracting archive - Installing laravel/serializable-closure (v1.3.3): Extracting archive - Installing laravel/prompts (v0.1.13): Extracting archive - Installing laravel/framework (v10.32.1): Extracting archive - Installing symfony/yaml (v6.3.8): Extracting archive - Installing laravel/sail (v1.26.0): Extracting archive - Installing laravel/sanctum (v3.3.2): Extracting archive - Installing nikic/php-parser (v4.17.1): Extracting archive - Installing psy/psysh (v0.11.22): Extracting archive - Installing laravel/tinker (v2.8.2): Extracting archive - Installing hamcrest/hamcrest-php (v2.0.1): Extracting archive - Installing mockery/mockery (1.6.6): Extracting archive - Installing filp/whoops (2.15.4): Extracting archive - Installing nunomaduro/collision (v7.10.0): Extracting archive - Installing sebastian/version (4.0.1): Extracting archive - Installing sebastian/type (4.0.0): Extracting archive - Installing sebastian/recursion-context (5.0.0): Extracting archive - Installing sebastian/object-reflector (3.0.0): Extracting archive - Installing sebastian/object-enumerator (5.0.0): Extracting archive - Installing sebastian/global-state (6.0.1): Extracting archive - Installing sebastian/exporter (5.1.1): Extracting archive - Installing sebastian/environment (6.0.1): Extracting archive - Installing sebastian/diff (5.0.3): Extracting archive - Installing sebastian/comparator (5.0.1): Extracting archive - Installing sebastian/code-unit (2.0.0): Extracting archive - Installing sebastian/cli-parser (2.0.0): Extracting archive - Installing phpunit/php-timer (6.0.0): Extracting archive - Installing phpunit/php-text-template (3.0.1): Extracting archive - Installing phpunit/php-invoker (4.0.0): Extracting archive - Installing phpunit/php-file-iterator (4.1.0): Extracting archive - Installing theseer/tokenizer (1.2.2): Extracting archive - Installing sebastian/lines-of-code (2.0.1): Extracting archive - Installing sebastian/complexity (3.1.0): Extracting archive - Installing sebastian/code-unit-reverse-lookup (3.0.0): Extracting archive - Installing phpunit/php-code-coverage (10.1.8): Extracting archive - Installing phar-io/version (3.2.1): Extracting archive - Installing phar-io/manifest (2.0.3): Extracting archive - Installing myclabs/deep-copy (1.11.1): Extracting archive - Installing phpunit/phpunit (10.4.2): Extracting archive - Installing spatie/backtrace (1.5.3): Extracting archive - Installing spatie/flare-client-php (1.4.3): Extracting archive - Installing spatie/ignition (1.11.3): Extracting archive - Installing spatie/laravel-ignition (2.3.1): Extracting archive 55 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi INFO Discovering packages. laravel/sail .......................................................... DONE laravel/sanctum ....................................................... DONE laravel/tinker ........................................................ DONE nesbot/carbon ......................................................... DONE nunomaduro/collision .................................................. DONE nunomaduro/termwind ................................................... DONE spatie/laravel-ignition ............................................... DONE 82 packages you are using are looking for funding. Use the `composer fund` command to find out more! > @php artisan vendor:publish --tag=laravel-assets --ansi --force INFO No publishable resources for tag [laravel-assets]. No security vulnerability advisories found > @php artisan key:generate --ansi INFO Application key set successfully. INFO Application ready! Build something amazing. Sail scaffolding installed successfully. WARN TTY mode requires /dev/tty to be read/writable. [+] Running 1/1 ⠿ mysql Pulled 2.8s [+] Building 3.3s (16/16) FINISHED => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 32B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/ubuntu:22.04 2.9s => [ 1/11] FROM docker.io/library/ubuntu:22.04@sha256:2b7412e6465c3c7fc5bb21d3e6f19 0.0s => [internal] load build context 0.0s => => transferring context: 99B 0.0s => CACHED [ 2/11] WORKDIR /var/www/html 0.0s => CACHED [ 3/11] RUN ln -snf /usr/share/zoneinfo/UTC /etc/localtime && echo UTC > 0.0s => CACHED [ 4/11] RUN apt-get update && mkdir -p /etc/apt/keyrings && apt-g 0.0s => CACHED [ 5/11] RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.2 0.0s => CACHED [ 6/11] RUN groupadd --force -g 20 sail 0.0s => CACHED [ 7/11] RUN useradd -ms /bin/bash --no-user-group -g 20 -u 1337 sail 0.0s => CACHED [ 8/11] COPY start-container /usr/local/bin/start-container 0.0s => CACHED [ 9/11] COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 0.0s => CACHED [10/11] COPY php.ini /etc/php/8.2/cli/conf.d/99-sail.ini 0.0s => CACHED [11/11] RUN chmod +x /usr/local/bin/start-container 0.0s => exporting to image 0.1s => => exporting layers 0.0s => => writing image sha256:e61d59045001df822f1a08d808ca8c3f27967fa59323ebf01871a1c2 0.0s => => naming to sail-8.2/app 0.0s Please provide your password so we can make some final adjustments to your application's permissions. Password: Thank you! We hope you build something incredible. Dive in with: cd sample-app && ./vendor/bin/sail up
アプリケーション名は、任意の名前で作成できます。
- 例えば、
?with=mysql,redis
をつけることで、MySQL と Redis を利用できます。 ?with=
をつけない場合、mysql、redis、meilisearch、mailpit、selenium が設定されます。- PostgreSQLを使用する場合は
mysql
をpgsql
に変更します。
1-2. Docker コンテナの起動
以下のコマンドで、Docker コンテナを起動します。
./vendor/bin/sail up
コマンド実行時ログ
# r_yamate @ mbp in ~/development [18:20:58] C:127 $ cd sample-app # r_yamate @ mbp in ~/development/sample-app [18:21:05] $ ./vendor/bin/sail up [+] Running 4/4 ⠿ Network sample-app_sail Created 0.2s ⠿ Volume "sample-app_sail-mysql" Created 0.0s ⠿ Container sample-app-mysql-1 Created 0.2s ⠿ Container sample-app-laravel.test-1 Crea... 0.4s Attaching to sample-app-laravel.test-1, sample-app-mysql-1 sample-app-mysql-1 | [Entrypoint] MySQL Docker Image 8.0.32-1.2.11-server sample-app-mysql-1 | [Entrypoint] Initializing database sample-app-mysql-1 | 2023-11-20T09:21:14.034867Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead. sample-app-mysql-1 | 2023-11-20T09:21:14.041155Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.32) initializing of server in progress as process 17 sample-app-mysql-1 | 2023-11-20T09:21:14.217630Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. sample-app-mysql-1 | 2023-11-20T09:21:16.522176Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. sample-app-laravel.test-1 | 2023-11-20 09:21:18,667 INFO Set uid to user 0 succeeded sample-app-laravel.test-1 | 2023-11-20 09:21:18,679 INFO supervisord started with pid 1 sample-app-laravel.test-1 | 2023-11-20 09:21:19,683 INFO spawned: 'php' with pid 16 sample-app-mysql-1 | 2023-11-20T09:21:20.076140Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option. sample-app-laravel.test-1 | 2023-11-20 09:21:20,686 INFO success: php entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Web ブラウザで http:// localhost
にアクセスし、Laravel のデフォルトページが表示されれば成功です。
Ctrl
+ C
キーで Sail を一度停止します。
1-3. sail
コマンドエイリアスの設定
以下のコマンドで、./vendor/bin/sail
のエイリアスを設定します。
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
以下のコマンドを実行します。
sail up -d
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:23:19] C:130 $ alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail' # r_yamate @ mbp in ~/development/sample-app [18:29:18] $ sail up -d [+] Running 2/2 ⠿ Container sample-app-mysql-1 Started 0.8s ⠿ Container sample-app-laravel.test-1 Star... 3.9s
sail up
の後に -d
をつけていますが、バックグラウンドで Sail を起動するためのオプションです。
http://localhost
でアクセスし、同じく Laravel のデフォルトページが表示されれば OK です。
2. React の開発環境構築
React の環境は Laravel 内に設定します。resources ディレクトリ内に ts ディレクトリを作成し、 Laravel に同梱されている node、npm、npx を使用します。
構築した Laravel の開発環境にインストールされた node や npm、npx を確認します。
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:29:27] $ sail node --version v20.9.0 # r_yamate @ mbp in ~/development/sample-app [18:32:20] $ sail npm --version 10.2.2 # r_yamate @ mbp in ~/development/sample-app [18:32:32] $ sail npx --version 10.2.2
2-1. 必要なモジュールのインストール
以下のコマンドを実行し、package.json ファイル内に記述されたパッケージ( Laravel で Vite を使うのに必要なものなど)を一括でインストールします。
sail npm install sail npm install -D react react-dom @types/react @types/react-dom sail npm install -D @vitejs/plugin-react
node_modules
ディレクトリ と package-lock.json
も同時に作成されます。
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:32:35] $ sail npm install sail npm install -D react react-dom @types/react @types/react-dom sail npm install -D @vitejs/plugin-react added 20 packages, and audited 21 packages in 17s 5 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 10 packages, and audited 31 packages in 5s 5 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 60 packages, and audited 91 packages in 23s 9 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
2-2. TypeScript の導入
以下のコマンドで、TypeScript を導入します。
sail npm install -D typescript sail npx tsc --init --jsx react-jsx
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:35:19] $ sail npm install -D typescript sail npx tsc --init --jsx react-jsx added 1 package, and audited 92 packages in 15s 9 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Created a new tsconfig.json with: TS target: es2016 module: commonjs jsx: react-jsx strict: true esModuleInterop: true skipLibCheck: true forceConsistentCasingInFileNames: true You can learn more at https://aka.ms/tsconfig
tsconfig.json がルートディレクトリに作成されます。
2-3. Vite の設定
vite.config.js の設定を以下のように更新します。
- 編集:vite.config.js
import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import react from '@vitejs/plugin-react'; // 追加 export default defineConfig({ plugins: [ laravel({ // TypeScriptとSassが使えるように変更 // input: ['resources/css/app.css', 'resources/js/app.js'], input: [ 'resources/sass/app.scss', 'resources/ts/index.tsx' ], refresh: true, }), react(), // 追加 ], });
2-4. index.blade.php の作成
resources/views ディレクトリ内に index.blade.php を作成します。welcome.blade.php は、削除します。
- 作成:resources/views/index.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>sample-app</title> @viteReactRefresh @vite(['resources/sass/app.scss', 'resources/ts/index.tsx']) </head> <body class="antialiased"> <div id="app"></div> </body> </html>
2-5. index.tsx の作成
resources ディレクトリ内に ts ディレクトリを追加し、index.tsx を作成します。
- 作成:resources/ts/index.tsx
import React from 'react'; import { createRoot } from 'react-dom/client'; const container = document.getElementById('app'); const root = createRoot(container!); root.render( <React.StrictMode> <div className="text-blue"> Hello World! </div> </React.StrictMode>, );
2-6. web.php の編集
welcome
を index
に変更します。
- 編集:routes/web.php
<?php use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider and all of them will | be assigned to the "web" middleware group. Make something great! | */ Route::get('/', function () { // return view('welcome'); return view('index'); });
2-7. Sass の導入
sass
のパッケージをインストールします。
sail npm install -D sass
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:37:19] $ sail npm install -D sass added 15 packages, and audited 107 packages in 7s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
resources/css/app.css を resources/sass/app.scss に変更し、サンプルでスタイルを設定します。
- 編集:resources/sass/app.scss
.text-blue { color: blue; }
2-8. React と Sass の動作確認
以下のコマンドを実行します。
sail npm run dev
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app [18:45:10] $ sail npm run dev > dev > vite VITE v4.5.0 ready in 1492 ms ➜ Local: http://localhost:5173/ ➜ Network: http://192.168.32.3:5173/ ➜ press h to show help LARAVEL v10.32.1 plugin v0.8.1 ➜ APP_URL: http://localhost
http://localhost
にアクセスし、青文字で Hello World!
と表示されれば成功です。
3. Laravel と React の連携
最後に、Laravel と React の連携を確認します。
3-1. App.tsx の作成
resources/ts ディレクトリ内に App.tsx を作成します。
- 作成:resources/ts/App.tsx
import React, { useEffect } from 'react'; import axios from 'axios'; const App: React.FC = () => { useEffect(()=>{ const fetchFromLaravel = async () => { const res = await axios.get(`/api/hoge`); alert(res.data.hoge) }; fetchFromLaravel(); }, []) return ( <div className="App"></div> ); } export default App;
3-2. index.tsx の編集
- 編集:resources/ts/index.tsx
import React from 'react'; import { createRoot } from 'react-dom/client'; import App from './App'; // 追加 const container = document.getElementById('app'); const root = createRoot(container!); root.render( <React.StrictMode> <div className="text-blue"> Hello World! </div> <App /> {/* 追加 */} </React.StrictMode>, );
3-3. api.php の編集
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider and all of them will | be assigned to the "api" middleware group. Make something great! | */ Route::get('/regi', function (Request $request) { return response()->json(['regi' => 'Hello Laravel!']); });
http:// localhost
にアクセスし、Alert で Hello Laravel!
と表示されれば、Laravel と React の連携は完了です。
Ctrl
+C
キーで Vite を停止します。
Sail を停止します。
sail down
おわりに
今回は、Laravel 10 と React 18 を使用した SPA 開発環境を Laravel Sail を活用して構築する手順をまとめました。
ありがとうございました。
今日からリモートワークの空間に草を置いた。 pic.twitter.com/OaqZZC4Wxf
— やまて|Web系エンジニア2年目 (@r_yamate) 2023年11月6日
枯らさないように。