はじめに
Laravelでvue.jsを使った開発をするときは
laravel-mix付属のホットリロード機能(HMR)が便利です。
ただ、ホストで動かすことが想定されており、dockerベースでHMRな開発環境を作ろうとして戸惑ったので情報を整理します。
概要
Laravel6 + vue.js on Docker な環境でHMRをする設定を説明します。
Laradockは使いません。
ホスト側にバージョン管理が必要なツールはあまり入れたくないため、すべてDockerコンテナ内で完結させる方針です。
(yarnの実行はコンテナ内で実行すると遅いのですが、Ubuntu 上ではそれほど違いが感じられなかったため、コンテナ内で行う場合について記載しております。)
環境
- Ubuntu 18.04
- Docker 19.03.5
- docker-compose 1.25.0
- Laravel 6
結論
- WebサーバーはLaravelのビルドインサーバーを使う
- PHPとNode.jsは同じコンテナに設定
- Webpackのプロキシ機能で8080のアクセスを8000ポート(ビルドインサーバー)に転送
ソースはこちら
https://github.com/odaryo/laravel6_vuejs_HMR
環境構築について
ディレクトリ構成
┬- docker (Dockerの設定)
│ └- app
│ ├- conf.d (php設定ファイル)
│ │ ├- php_settings.ini
│ │ └- xdebug.ini
│ └- Dockerfile
├- src (Laravelディレクトリ)
└- docker-compose.yml
Docker環境
docker-compoe
appコンテナにはLaravelのビルドインサーバーを起動する設定を記載しています
version: '3'
services:
# laravel
app:
build:
context: ./
dockerfile: ./docker/app/Dockerfile
depends_on:
- db
links:
- db
volumes:
- ./app:/app:cached
- ./docker/app/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
- ./docker/app/conf.d/php_settings.ini:/usr/local/etc/php/conf.d/php_settings.ini
command: bash -c "php artisan serve --host 0.0.0.0" # 起動時にビルドインサーバーを起動
ports:
- "8000:8000" # php artisan serve 用のポート
- "8080:8080" # HMR用のポート
# DB (mysql)
db:
image: mysql:8
environment:
- MYSQL_DATABASE=testdb
- MYSQL_USER=testuser
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Tokyo
restart: always
volumes:
- dev_mysql_data:/var/lib/mysql
ports:
- "33306:3306"
volumes:
dev_mysql_data:
driver: local
Dockerfile
PHPコンテナとNode.jsコンテナに分けるとうまく行かなかったため、マルチステージビルドの形でPHPコンテナにNode.jsを追加する
# Nodeイメージ
FROM node:13-alpine as node
# PHPイメージ
FROM php:7.3-alpine
# Laravel環境に必要なパッケージをインストール
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
bash \
git \
unzip \
libpng \
libpng-dev \
libjpeg \
icu \
icu-dev \
icu-libs \
libxml2 \
libxml2-dev \
openssl \
openssl-dev \
&& docker-php-ext-install \
pdo_mysql \
mysqli \
gd \
mbstring \
intl \
xml \
opcache \
&& docker-php-ext-enable intl mbstring \
&& apk --update --no-cache add autoconf g++ make \
# xdebugインストール
&& pecl install -f xdebug \
&& docker-php-ext-enable xdebug \
&& apk del --purge autoconf g++ make
# Composerのインストール
RUN curl -sS https://getcomposer.org/installer | php ;mv composer.phar /usr/local/bin/composer;
RUN composer global require hirak/prestissimo \
&& composer global require phpunit/phpunit
# Nodeコンテナからyarnとnodeをコピー
COPY --from=node /opt/yarn-v* /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
# 使いやすいようにシンボリックリンク作成
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg
# ホスト側とuser_id, group_idを合わせる
ARG USER_ID
ARG GROUP_ID
RUN addgroup -g ${GROUP_ID} -S app-user && \
adduser -u ${USER_ID} -S app-user -G app-user
USER app-user:app-user
# Setup working directory
WORKDIR /app
参考
構築手順
docker起動
$ docker-compose build
$ docker-compose up -d
laravelインストール
appコンテナに入って実行します。
※laravelインストールまではコンテナが起動しないため、runコマンドで実行する必要があります。
$ docker-compose run app /bin/bash
$ composer create-project --prefer-dist laravel/laravel .
vue.jsを使う設定
laravel 6.0からデフォルトではインストールされないため、laravel/uiからインストールします。
$ composer require laravel/ui --dev
$ php artisan ui vue
$ exit
ここでdockerを再起動しておく
$ docker-compose up -d
http://localhost:8000
にアクセスして、スタート画面が表示されたらOK
node_moduleのインストール
$ docker-compose exec app yarn
HMRの設定
ホットリロードの確認用に、welcome.blade.phpのbody内にVue.jsのComponentを追加しておく
Componentはインストール時に作成されるサンプルを使用
<div id="app">
<example-component></example-component>
</div>
<script src="{{ mix('js/app.js') }}"></script>
webpack.mix.jsにHMRの設定を追加
8080へのアクセスではエラーとなりCannot GET /
が表示されてしまうため、ビルドインサーバーの8000ポートへプロキシしてやります
mix.webpackConfig({
devServer: {
host: '0.0.0.0',
port: 8080,
proxy: {
'*': 'http://0.0.0.0:8000'
},
// Windows(Docker for windows)の場合は下記を追加する
// watchOptions:{
// aggregateTimeout:200,
// poll:5000
// },
}
});
ホットリロードの実行
$ docker-compose exec app yarn hot
http://localhost:8080
へアクセスして、コンポーネントの内容が表示されれば完了です。
コンポーネントを修正して、変更が反映されることを確認しましょう。
参考
終わりに
ホットリロードでフロントエンド開発が捗ります。
注意点としては、HMRで監視するファイルはJavascriptやCSSなので、blade自体を更新した場合はブラウザの更新が必要となります。