Nuxt.js2.10とLaravel(6.0)を同一ディレクトリで動かすnuxt-laravelをDockerで環境構築

# 背景

[m2sd/nuxt-laravel
](https://github.com/m2sd/nuxt-laravel)をDockerで動作させるのに苦労したので備忘録として

## 前提条件

- macOS Mojave
- Laravel6.0の環境構築ができている(Dockerで)
- Docker for Macをインストール済

## Dockerの設定

[Laravelのローカル環境をDockerを利用してSSLからLaravel Duskの設定まで](https://qiita.com/ProjectEuropa/items/81368cae59f786cf6f0f)
これらを参照する。

```
_docker-configs
├── docker-compose.yml #編集
├── nginx
│   ├── cert-key
│   └── nginx.conf
├── php-fpm
│   └── Dockerfile #編集
```


```docker-compose.yml
version: "3"
services:
  nginx:
    image: nginx:alpine
    depends_on:
      - php-fpm
    ports:
      - 80:80
      - 443:443
    volumes:
      - ../:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/cert-key:/etc/nginx/ssl
  php-fpm:
    build: ./php-fpm
    ports:
      - 9000:9000
      - 8001:8001
      - 3000:3000
    environment:
      - HOST=0.0.0.0
    working_dir: /var/www/html
    volumes:
      - ../:/var/www/html
# DBの設定などは一旦省略する
```

```Dockerfile

FROM node:12.13.0-alpine as node

FROM php:7.3-fpm-alpine

## PDOなどインストールは省略

WORKDIR /var/www/html

# マルチステージビルドでphp-fpmコンテナにnodeとnpmを追加する
COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/
RUN ln -s /usr/local/bin/node /usr/local/bin/nodejs \
    && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
    && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx

RUN npm install -g npx @vue/cli
```

Dockerfileのビルドと実行とコンテナに入る。
docker-compose.ymlのあるディレクトリで以下を実行。

```
$ docker-compose build
$ docker-compose up -d
$ docker-compose exec php-fpm sh
```

## Laravelのresources/nuxtにNuxtを入れる

コンテナにて

```
/var/www/html # npx create-nuxt-app resources/nuxt
```

選択肢は適当に。

Nuxtのインストールが完了したら、Nuxtの設定関連ファイル群をLaravelのRootディレクトリに移動させる。

```
/var/www/html # cd resources/nuxt
/var/www/html/resources/nuxt # mv .babelrc jest.config.js nuxt.config.js package-lock.json package.json ../..
/
```

設定ファイル群を移動すると以下のようなディレクトリ構成になる

```
.
├── _docker-configs
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── jest.config.js
├── node_modules
├── nuxt.config.js
├── package-lock.json
├── package.json
├── phpunit.xml
├── public
├── readme.md
├── resources
├── routes
├── server.php
├── storage
├── tests
├── vendor
└── webpack.mix.js
```

一旦LaravelのRootディレクトリに戻り、nuxt-laravelと必要なモジュールをnpmでインストールする。

```
/var/www/html/resources/nuxt # cd -
/var/www/html # npm i -D nuxt-laravel@next @nuxtjs/axios @nuxtjs/proxy
```

## nuxt.config.jsを編集

```nuxt.config.js
module.exports = {
  srcDir: 'resources/nuxt', //追加
  mode: 'spa', //追加
  modules: [
    'nuxt-laravel', //追加
  ],
  router: {
    base: "/app/" //追加 任意のディレクトリ名
  },
}
```

## Nuxtの開発環境サーバーを動かす

`npm run dev`実行後、[localhost:3000/app/](http://localhost:3000/app/)にアクセス

```
/var/www/html # npm run dev
```

Nuxtのデフォルトが見えればおｋ。

## LaravelでのテストAPI作成

`routes/api.php`を編集,以下のコードを追加

```api.php
Route::middleware('api')->get('/test', function (Request $request) {
    return [
        'test'
    ];
});
```

[api/test](https://localhost/api/test)をたたいて、TestとでればOK

[![Image from Gyazo](https://i.gyazo.com/d8c13545a856be17a1254da2b1b881bc.png)](https://gyazo.com/d8c13545a856be17a1254da2b1b881bc)

## NuxtデフォルトページにAPIを組み込む

`resources/nuxt/pages/index.vue`を編集

```index.vue
<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        {{title}}
      </h1>
      <h2 class="subtitle">
        My world-class Nuxt.js project
      </h2>
      <div class="links">
        <a
          href="https://nuxtjs.org/"
          target="_blank"
          class="button--green"
        >
          Documentation
        </a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey"
        >
          GitHub
        </a>
      </div>
    </div>
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  data() {
    return {
      title: ''
    }
  },
  mounted() {
    this.$axios.get('https://localhost/api/test').then(response => {
      this.title = response.data;
    });
  },
}
</script>

<style>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>
```

** 開発環境サーバーだとCORSでAPI読み込めないので、[ここらへんの記事](https://qiita.com/naokada/items/394c1d85ad2975ba62f0)を参照にしてください。
本記事では一旦スルーします。

## Laravelのroutes/web.phpの編集

Nuxt.jsで設定したファイルが呼び出されるようにルーティングを編集

```web.php
Route::get(
    '{uri}',
    '\\'.Pallares\LaravelNuxt\Controllers\NuxtController::class
)->where('uri', '.*');
```

## Nuxt.jsの本番用のビルド

`npm run build`で静的ファイルを吐き出します。

```
/var/www/html # npm run build
```

[localhost](https://localhost/)にアクセスして

以下の画像が出ればOK。
[![Image from Gyazo](https://i.gyazo.com/8ccce4a64285176c349ec7e76572160a.png)](https://gyazo.com/8ccce4a64285176c349ec7e76572160a)

** このままの状態だと開発環境サーバーでは `/app/`に対して本番では`/`でアクセスする違いに気持ち悪さがあるかもしれない..。また肝心のLaravelがAPIだけしか使えないので注意。

routes/web.phpを以下のように変更すれば、

```web.php
Route::get('/', function () {
    return view('welcome');
});

Route::get(
    'app/subpage{path}',
    '\\'.Pallares\LaravelNuxt\Controllers\NuxtController::class
)->where('path', '.*')
 // Redirect to a spcific subpage/<path> from within Laravel
 // by using Laravels route helper
 // e.g.: `route('nuxt.subpage', ['path' => '/<path>'])`
 ->name('nuxt.subpage');
```

[localhost/app/subpage](https://localhost/app/subpage)でNuxtで作成したページが見れる。
それ以外でLaravelで作成した画面も共存できる。

## 参考

[m2sd/nuxt-laravel](https://github.com/m2sd/nuxt-laravel)
[skyrpex/laravel-nuxt](https://github.com/skyrpex/laravel-nuxt)