Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Nuxt.jsとLaravelを同じリポジトリで管理し、Valetで動かすまで

More than 1 year has passed since last update.

表題の通りです。
Nuxt.jsやLaravel、Valetが何なのかは省略。
やりたいこととしては、

  • Nuxt.jsとLaravelは同じディレクトリ(リポジトリ)で共存させる。
  • Nuxt.jsはSPAとする。
  • LaravelはAPI専用とする。
  • Nuxt.jsからLaravelのAPIを呼び出してレスポンスを表示する。
  • 最終的に両方ともLaravel Valetで動かせるようにする。

インストール

まずは公式ドキュメントを参考にValetのインストール。

https://laravel.com/docs/5.6/valet

Valetで管理するディレクトリ以下にLaravelをインストールする。
バージョンは5.6
プロジェクト名はlaranuxtとする。

$ composer create-project --prefer-dist laravel/laravel laranuxt

Valetが動いているのですぐに表示できる。
ドメインが.testとなっているのはValetの設定を変えたため(自分いつ変えたんだ:thinking:)

スクリーンショット 2018-04-24 18.26.24.png

続いてNuxt.jsのインストール。
今回はLaravelで作られたresourcesディレクトリの下にインストールする。
インストール先のディレクトリ名はnuxtとする。

https://ja.nuxtjs.org/guide/installation

$ cd /path/to/laranuxt/resources
$ vue init nuxt-community/starter-template nuxt
$ cd nuxt
$ npm install
$ npm run dev

スクリーンショット 2018-04-24 18.49.20.png

これはValetではないことに注意。

Nuxt.jsでシンプルな画面を作ってみる

Nuxt.jsとLaravelを組み合わせる前にNuxt.jsでシンプルな画面遷移を作ってみる。
作成するpagesディレクトリの構造を以下に示す。

pages/
--| message/
-----| hello.vue
-----| goodbye.vue
--| index.vue
pages/index.vue
<template>
  <section class="container">
    <div>
      <app-logo/>
      <h1 class="title">
        LaraNuxt
      </h1>
      <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 class="links">
        <a
          href="message/hello"
          class="button--green">Hello</a>
        <a
          href="message/goodbye"
          class="button--grey">Good bye</a>
      </div>
    </div>
  </section>
</template>

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

export default {
  components: {
    AppLogo
  }
}
</script>
pages/message/hello.vue
<template>
  <section class="container">
    <div>
      <h1 class="title">
        Hello!
      </h1>
      <div class="links">
        <a
          href="../"
          class="button--green">Nuxt Top</a>
      </div>
    </div>
  </section>
</template>

<script>
</script>
pages/message/goodbye.vue
<template>
  <section class="container">
    <div>
      <h1 class="title">
        Good bye!
      </h1>
      <div class="links">
        <a
          href="../"
          class="button--green">Nuxt Top</a>
      </div>
    </div>
  </section>
</template>

<script>
</script>

スクリーンショット 2018-04-24 19.03.51.png
スクリーンショット 2018-04-24 19.04.02.png

Nuxt.jsとLaravelの合体

最初にNuxt.jsをSPAとしてビルドする。
nuxt.config.jsmode: 'spa'を追加してビルド。

$ npm run build

これで公開用のdistディレクトリが作成される。
続いてLaravelのpublicディレクトリ以下にdistへのシンボリックリンクを作成する。

$ ln -s /path/to/laranuxt/resources/nuxt/dist /path/to/laranuxt/public/nuxt

Valetからアクセスできるか。

スクリーンショット 2018-04-24 19.14.02.png

だめでした:sob:

そこで、/nuxt/以下はNuxt.jsのファイルを読み込めるよう、Valetのドライバーを作る。
以下を参考。

https://laracasts.com/discuss/channels/servers/possible-to-use-htaccess-files-using-valet
https://gist.github.com/jakecobley/366ae401f44f53bbaa65dcd7371050c2

/nuxt/以下へのリクエストで静的ファイルが存在しないものはすべて/public/nuxt/index.htmlを読み込むようにする。

$ cp ~/.valet/Drivers/SampleValetDriver.php ~/.valet/Drivers/NuxtValetDriver.php
NuxtValetDriver.php
<?php

class NuxtValetDriver extends ValetDriver
{
    /**
     * Determine if the driver serves the request.
     *
     * @param  string  $sitePath
     * @param  string  $siteName
     * @param  string  $uri
     * @return bool
     */
    public function serves($sitePath, $siteName, $uri)
    {
        if (strpos($uri, 'nuxt') !== false) {
            return true;
        }

        return false;
    }

    /**
     * Determine if the incoming request is for a static file.
     *
     * @param  string  $sitePath
     * @param  string  $siteName
     * @param  string  $uri
     * @return string|false
     */
    public function isStaticFile($sitePath, $siteName, $uri)
    {
        $staticFilePath = $sitePath.'/public'.$uri;
        if (file_exists($staticFilePath)
            && !is_dir($staticFilePath)
            && pathinfo($staticFilePath)['extension'] != 'php') {
            return $staticFilePath;
        }

        return false;
    }

    /**
     * Get the fully resolved path to the application's front controller.
     *
     * @param  string  $sitePath
     * @param  string  $siteName
     * @param  string  $uri
     * @return string
     */
    public function frontControllerPath($sitePath, $siteName, $uri)
    {
        return $sitePath.'/public/nuxt/index.html';
    }
}

もうひとつやらなければいけないことは、Nuxt.jsのベースURLを変更すること。

https://ja.nuxtjs.org/api/configuration-router

nuxt.config.jsrouter: {base: '/nuxt/'}を追加してビルド。

果たして、、、

スクリーンショット 2018-04-24 19.31.05.png

成功!!:joy::joy::joy:
ドメインを見ると確かにValetです。

スクリーンショット 2018-04-24 19.32.29.png

画面遷移も成功。

スクリーンショット 2018-04-24 19.33.19.png

それでいてトップページはLaravel。

LaravelでAPI作成

routes/api.phpに文字列を返すだけのシンプルなAPIを作成する。

routes/api.php
<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Route::get('hello', function () {
    return 'Hello! from Laravel';
});

Route::get('goodbye', function () {
    return 'Good bye! from Laravel';
});

スクリーンショット 2018-04-24 19.37.43.png

Nuxt.jsからLaravelのAPIを呼んでレスポンスを表示

Nuxt.jsにaxiosをインストール

$ cd /path/to/laranuxt/resources/nuxt
$ npm install --save axios

nuxt.config.jsvendorを追加。

nuxt.config.js
module.exports = {

  ....

  build: {
    vendor: ['axios']
  }

  ....
}
pages/message/hello.vue
<template>
  <section class="container">
    <div>
      <h1 class="title">
        {{ message }}
      </h1>
      <div class="links">
        <a
          href="../"
          class="button--green">Nuxt Top</a>
      </div>
    </div>
  </section>
</template>

<script>
import axios from 'axios'
export default {
  asyncData () {
    return axios.get('/api/hello')
    .then((msg) => {
      return { message: msg.data }
    })
  }
}
</script>
pages/message/goodbye.vue
<template>
  <section class="container">
    <div>
      <h1 class="title">
        {{ message }}
      </h1>
      <div class="links">
        <a
          href="../"
          class="button--green">Nuxt Top</a>
      </div>
    </div>
  </section>
</template>

<script>
import axios from 'axios'
export default {
  asyncData () {
    return axios.get('/api/goodbye')
    .then((msg) => {
      return { message: msg.data }
    })
  }
}
</script>

そしてビルド。

スクリーンショット 2018-04-24 19.48.16.png

できた〜〜:joy:

まとめ

正直なところ、シンプルな構成にしたいならNuxt.jsとLaravelを同じリポジトリにしないで別々に管理したほうがよいと思う(身も蓋もなし:joy:)

もしかしたらもっと楽な方法があるのかもしれないけど、今回Valetで確認するためにいちいちNuxt.jsをビルドするのが面倒だった(watch and build的なのがあるのかな)。
手軽に確認するためにnpm run devを使おうとしたが、そうするとAPIとの通信においてCORSで引っかかってしまう。
このあたりどうしたものか。

参考

https://ja.nuxtjs.org/
https://laracasts.com/discuss/channels/servers/possible-to-use-htaccess-files-using-valet
https://gist.github.com/jakecobley/366ae401f44f53bbaa65dcd7371050c2
http://techblog.scouter.co.jp/entry/2017/11/02/120748
https://qiita.com/mikakane/items/a76b230d91dc5ae80574

kiyc
Webエンジニア。インフラもバックエンドもフロントエンドも書いています。 普段書いているのはPHP(Laravel)、JavaScript(Vue.js)です。
prime-order
組織と業務に変革をもたらす新しいカタチのシステム開発サービス
https://prime-order.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away