表題の通りです。
Nuxt.jsやLaravel、Valetが何なのかは省略。
やりたいこととしては、
- Nuxt.jsとLaravelは同じディレクトリ(リポジトリ)で共存させる。
- Nuxt.jsはSPAとする。
- LaravelはAPI専用とする。
- Nuxt.jsからLaravelのAPIを呼び出してレスポンスを表示する。
- 最終的に両方ともLaravel Valetで動かせるようにする。
インストール
まずは公式ドキュメントを参考にValetのインストール。
Valetで管理するディレクトリ以下にLaravelをインストールする。
バージョンは5.6
プロジェクト名はlaranuxt
とする。
$ composer create-project --prefer-dist laravel/laravel laranuxt
Valetが動いているのですぐに表示できる。
ドメインが.test
となっているのはValetの設定を変えたため(自分いつ変えたんだ)
続いてNuxt.jsのインストール。
今回はLaravelで作られたresources
ディレクトリの下にインストールする。
インストール先のディレクトリ名はnuxt
とする。
$ cd /path/to/laranuxt/resources
$ vue init nuxt-community/starter-template nuxt
$ cd nuxt
$ npm install
$ npm run dev
これはValetではないことに注意。
Nuxt.jsでシンプルな画面を作ってみる
Nuxt.jsとLaravelを組み合わせる前にNuxt.jsでシンプルな画面遷移を作ってみる。
作成するpages
ディレクトリの構造を以下に示す。
pages/
--| message/
-----| hello.vue
-----| goodbye.vue
--| 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>
<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>
<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>
Nuxt.jsとLaravelの合体
最初にNuxt.jsをSPAとしてビルドする。
nuxt.config.js
にmode: 'spa'
を追加してビルド。
$ npm run build
これで公開用のdist
ディレクトリが作成される。
続いてLaravelのpublic
ディレクトリ以下にdist
へのシンボリックリンクを作成する。
$ ln -s /path/to/laranuxt/resources/nuxt/dist /path/to/laranuxt/public/nuxt
Valetからアクセスできるか。
だめでした
そこで、/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
<?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を変更すること。
nuxt.config.js
にrouter: {base: '/nuxt/'}
を追加してビルド。
果たして、、、
成功!!
ドメインを見ると確かにValetです。
画面遷移も成功。
それでいてトップページはLaravel。
LaravelでAPI作成
routes/api.php
に文字列を返すだけのシンプルなAPIを作成する。
<?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';
});
Nuxt.jsからLaravelのAPIを呼んでレスポンスを表示
Nuxt.jsにaxiosをインストール
$ cd /path/to/laranuxt/resources/nuxt
$ npm install --save axios
nuxt.config.js
にvendor
を追加。
module.exports = {
....
build: {
vendor: ['axios']
}
....
}
<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>
<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>
そしてビルド。
できた〜〜
まとめ
正直なところ、シンプルな構成にしたいならNuxt.jsとLaravelを同じリポジトリにしないで別々に管理したほうがよいと思う(身も蓋もなし)
もしかしたらもっと楽な方法があるのかもしれないけど、今回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