LoginSignup
32
26

More than 3 years have passed since last update.

Docker + Laravel6 + vue-cli3でホットリロードなフロントエンド開発環境を得る。

Posted at

Laravelのフロントエンド開発にvue-cliを導入したい。
あると思います。

本記事では、Laravel6にvue-cliを利用して
yarn serveでフロントエンドの開発環境の導入をしてみたいと思います。

なお、本記事で使用したソースはこちらに置いております。
https://github.com/kyhei/qiita-laravuel6

開発環境

  • macOS Mojave 10.14.4
  • Docker Desktop for Mac 2.1.0.2
    • Engine 19.03.2
    • Compose 1.24.1
  • Laravel 6.0
  • vue-cli 3.11

Dockerイメージの構成と構築

Docker Composeするイメージ郡概要

スクリーンショット 2019-09-09 11.34.55.png
上記のような構成をDocker Composeで構築したいと思います。
MYSQL、phpMyAdmin,Mailhogは本記事の中では使用しませんのでお好みでお願いします。

要点としては

  • Nginxコンテナで受けたHTTPリクエストをPHP-fpm上で処理する
  • Laravelのインストールやvue-cliの実行はwork-spaceコンテナで行う

の2点です。

Laravel Serverについて

今回は以下のような構成でLaravelサーバを構築しました。
スクリーンショット 2019-09-09 11.51.13.png
Nginxコンテナで受けたリクエストをUNIXソケット経由でPHP-fpmに伝えるという構成です。
これらの3つのコンテナ郡を便宜上Laravel Serverと呼ぶことにします。

Dev Serverについて

開発作業を行うwork-spaceコンテナ上でyarn serveするためこちらのコンテナはそのままポートを外部に開放しております。
スクリーンショット 2019-09-09 12.01.51.png
work-spaceコンテナの特徴は下記の点です。

  • composer create-project laravel/laravelができる。
  • php artisan migrate等が実行できる。
  • yarn serve等Node.jsの実行ができる。

VSCodeやシェルから中に入って作業を行うためのコンテナです。
ローカルのプロジェクトディレクトリは/work以下にバインドしております。

Docker及びDocker Composeの定義ファイルは下記をご参照くださいませ。
https://github.com/kyhei/qiita-laravuel6

Laravelとvue-cliのインストール

ここからようやくコードを書いて参ります。
とりあえずDocker Composeをupしておきましょう。

$ git clone https://github.com/kyhei/qiita-laravuel6.git
$ cd qiita-laravuel6
$ docker-compose up -d

コンテナを確認するとこんな感じになるかと思います。
スクリーンショット 2019-09-09 12.43.58.png

workspaceコンテナに以下のコマンドで接続します。

$ docker-compose exec workspace bash

Composerはインストール済みですので早速Laravelをインストールしましょう。

/work# composer create-project --prefer-dist laravel/laravel laravuel
/work# ls
docker  docker-compose.yml  laravuel

カレントディレクトリ下にLaravelプロジェクトのフォルダが作成されていたらOKです。

続いてNginxコンテナのドキュメントルートを作成したLaravelプロジェクトのpublicディレクトリに設定します。

/docker/nginx/default.conf
server {
    listen 80;
    root /work/laravuel/public; # <- ここに設定
〜後略〜

設定を反映させるためにNginxコンテナを再起動しましょう。

/work# exit
$ docker-compose restart nginx

コンテナの再起動を確認後、ブラウザからLaravelのHello world画面が表示されていればOKです。
http://localhost:8000

vue-cliによるフロントエンド雛形作成

再びworkspaceコンテナにログインします。

$ docker-compose exec workspace bash 
/work#

まずはvue-cliをグローバルにインストールしましょう。

/work# yarn global add @vue/cli
/work# which vue
/usr/local/bin/vue

つづいてフロントエンドの雛形を作成します。

/work# cd laravuel
/work/laravuel# vue create frontend

何をインストールするか色々聞かれますが
vue routerとhistoryモードを有効化にしたらあとはお好みで構いません。
(本記事ではTypeScript + vue-property-decoratorを使用しております。)

yarn serveでvue-cliの初期画面を表示してみましょう。
まずはvue.config.jsファイルを作成しdevServerがリッスンするポートを指定します。

laravuel/frontend/vue.config.js
module.exports = {
  devServer: {
    port: 9001
  }
}

次にyarn serveを実行します。

/work/laravuel# cd frontend
/work/laravuel/frontend# yarn serve

http://localhost:9001
で初期画面が表示されたらOKです。

本番用ビルドの設定

本項のvue.config.js及びpackage.jsonの設定内容は
Evan You氏の下記のリポジトリを参考にしております。
https://github.com/yyx990803/laravel-vue-cli-3

今回はフロントエンドをSPAで構築するため、Laravelはウェブページのリクエストが来たら
常に同じHTMLファイルを返す必要があります。
Laravelのルーティングを次のように書き換えましょう。

laravuel/routes/web.php
Route::get('/{any?}', function () {
  return view('index');
})->where('any', '.+');

簡単のためコントローラは用意せずクロージャで対応しました。
これで任意のリクエストに対してindex.blade.phpを返すことができます。

つづいてvue-cliの本番ビルド時に
laravuel/resources/views/index.blade.phpを作成するよう設定します。

laravuel/frontend/vue.config.js
module.exports = {
  devServer: {
    port: 9001
  },
  outputDir: '../public',
  assetsDir: 'assets',
  indexPath: process.env.NODE_ENV === 'production'
    ? '../resources/views/index.blade.php'
    : 'index.html'
}

なお、outputDirオプションにてCSSやJSファイルが配置されるパスを設定しています。
assetsDirオプションと組み合わせることで、ビルド結果のファイル郡は全て
public/assets下に配置されます。

最後にpublicディレクトリ下のindex.phpなど必要なファイルをビルド時に削除してしまわぬよう、package.jsonの内容を書き換えます。

laravuel/frontend/package.json
"scripts": {
  "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
+ "build": "rm -rf ../public/assets && vue-cli-service build --no-clean",
  "lint": "vue-cli-service lint"
},

--no-cleanオプションで既存のビルドファイル削除を無効しているため、
rmコマンドで既存ファイルを削除しています。

ここまでの設定を終えたらフロントエンドをビルドしましょう。

/work/laravuel/frontend# yarn build

publicディレクトリ下にassetsフォルダが作成され、
resources/views下にはindex.blade.phpが作成されたかと思います。

http://localhost:8000
でLaravel Serverにアクセスし、vue-cliの初期画面が表示されたらOKです。

Dev ServerからLaravel Serverへのプロキシ設定

vue-cliのDev serverとLaravel Serverはそれぞれ別々のコンテナ上で動作しているため、
Dev server上のvue-cliプロダクトからLaravelのAPIを叩くにはDev serverでプロキシする必要があります。
具体的には下記のような感じです。
スクリーンショット 2019-09-09 15.37.58.png

vue.config.jsのdevServer項目にproxyの設定を追加しましょう。

laravuel/frontend/vue.config.js
devServer: {
  port: 9001,
  proxy: {
    '^/api': {
      target: 'http://nginx'
    }
  }
}

workspaceコンテナとnginxコンテナはDockerの同一ネットワーク上に存在するため、
nginxというホスト名で名前解決が可能です。

環境構築及び設定については以上で完了です。
お疲れ様でした!

vue.config.jsの要点をまとめると、
開発環境に関わらず、

  • 出力先のファイル、ディレクトリをLaravel用に変更する。
  • フロント開発サーバとバックエンドのAPIサーバとのやり取りはproxyを設定する。

となります。

まとめとして、vue.config.jsファイル全文を載せておきます。

laravuel/frontend/src/vue.config.js
module.exports = {
  devServer: {
    port: 9001,
    proxy: {
      '^/api': {
        target: 'http://nginx'
      }
    }
  },

  outputDir: '../public',
  assetsDir: 'assets',

  indexPath: process.env.NODE_ENV === 'production'
    ? '../resources/views/index.blade.php'
    : 'index.html'
}

Dev ServerとLaravel Server間の通信ハンズオン

サンプルのAPIを作成

/api/pingとリクエストしたらJSONを返すシンプルなAPIを作成します。

laravuel/routes/api.php
Route::get('/ping', function () {
  return response()->json([
    'message' => 'pong'
  ], 200);
});

ブラウザで
http://localhost:8000/api/ping
とリクエストしたらJSON文字列が表示されるかと思います。

フロントエンドにHTTPクライアントの導入

今回はaxiosを導入してAPIを叩いてみます。

$ docker-compose exec workspace bash
work/# cd laravuel/frontend
work/laravuel/frontend# yarn add axios

インストールが完了したらaxiosインスタンスを作成する処理を記述します。

laravuel/frontend/src/modules/axios.ts
import axios from 'axios'
const axiosInstance = axios.create()
export default axiosInstance

HelloWorldコンポーネントの修正

HelloWorldコンポーネントを修正し、
Laravel Serverからのレスポンスをブラウザで表示してみます。

laravuel/frontend/src/components/HelloWorld.vue
<template>
  <div class="hello">
    <h2>Request for Laravel Server</h2>
    <h3>/api/ping</h3>
    <h3>Response: {{apiText}}</h3>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import axiosInstance from '@/modules/axios'
import { AxiosResponse } from 'axios'

interface Ping {
  message: string
}

@Component({})
export default class HelloWorld extends Vue {
  apiText: string | null = null

  async initialize() {
    const res: AxiosResponse<Ping> = await axiosInstance.get('/api/ping')
    if (res.status === 200) {
      this.apiText = res.data.message
    }
  }

  created() {
    this.initialize()
  }
}
</script>
<style scoped>
後略

TSを使っていない等の環境の違いについては適宜読み替えていただけたらと思います。
yarn serveを実行しDev Serverにアクセスしてみましょう。
http://localhost:9001
スクリーンショット 2019-09-09 17.37.46.png

成功です!!!
もちろんyarn serveの実行下ではホットリロード等、開発サーバの恩恵を得られますので
いろいろいじってみるとリアルタイムで変更が反映されるかと思います。

最後にyarn buildでフロントエンドをビルドし、
http://localhost:8000
で同じ結果を得られるか確認してみてください。

終わりに

Dockerの構築からハンズオンまで盛りだくさんになってしまいました。

フレームワークに依らず、
outputDirとdevServer.proxyの設定さえ上手いことできたら
後はいつものvue-cliで開発を進められる!!

ということが感じられてたら嬉しいです。

参考

使用したDockerイメージ

32
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
26