概要
最近、Laravel + Vue でのSPA開発を始めました。これまではReactでフロントを主に開発しており、LaravelはAPIサーバーとして完全に分離した形で利用、開発してました。
時たま自分でもAPIの追加で手を入れる程度のLaravelとの関わりだったのですが、VueでのSPA開発に始めるにいたり、ディレクトリ構成など、ちょっと悩みもあるのでスナップショットをここに記録することにしました。
仕事で利用しているそのものではないですが、構成は全く同じです。Vuex(3系)、VueRouter(2系)、Vuetify使います。
・・・
app───Http───Controllers
| ├─Mlv──IndexController.php ・・・ ディレクトリ名はプロジェクト名のprefix。I/Oがわかりやすいようにシンプルなインターフェースを心がける、かけたい。
| └─Controller.php ・・・ 触らない、つもり。
└─Libs──(...) ・・・ このディレクトリにビジネスロジック。Mlv以下のコントローラーから呼び出し。
resources──js──components──common──Header.vue
| | ├─pages──Top.vue ・・・ 基本的にページごとに単一ファイルコンポーネントをきる。
| | ├─store──index.js ・・・ ファイル分割どうしようかなと考えてる。
| | └─router──index.js ・・・ ファイル分割どうしようかなと考えてる。
| ├─ app.js
| ├─ App.vue
| └─ bootstrap.js
└─views──index.blade.php ・・・ bladeはこの一枚。
routes───api.php
└─web.php
・・・
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>bladeはこの一枚で</title>
</head>
<body>
<div id="app">
</div>
<script src=" {{ mix('js/app.js') }} "></script>
</body>
</html>
Route::get('/{any?}', function () {
return view('index');
});
<?php
namespace App\Http\Controllers\Mlv;
class IndexController extends Controller
{
public function index(){
return view("/index");
}
}
<template>
<v-app>
<Header />
<router-view></router-view>
<Footer />
</v-app>
</template>
<script>
import Header from './components/common/Header'
import Footer from './components/common/Footer'
export default {
name: 'app',
components : {
Header,
Footer
}
}
</script>
require('./bootstrap');
import Vue from 'vue'
import Vuetify from 'vuetify'
import Vuex from 'vuex'
import router from './router/index'
import store from './store/index'
import App from './App.vue'
Vue.use(Vuex)
Vue.use(Vuetify)
new Vue({
el: '#app',
store,
router,
components: { App },
template: '<App />'
})
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
user_session: {
logined: false,
}
},
getters:{
},
mutations: {
},
actions: {
}
})
export default store
import Vue from 'vue'
import Router from 'vue-router'
import Top from '../pages/Top'
import User from '../pages/User'
Vue.use(Router)
const routes = [
{
path: '/',
component: Top
},
{
path: '/User',
component: User
}
]
const router = new Router({
mode: 'history',
routes
})
export default router
<template>
<div>
<span class>Topページ</span>
<router-link to="/User">Userページへ</router-link>
</div>
</template>
<script>
export default {
}
</script>
<template>
<div>
<span class>Userページ</span>
<router-link to="/">Topページへ</router-link>
</div>
</template>
<script>
export default {
}
</script>
雑感
スタートがとにかくやさしい
React+Reduxの構成に比べたら、手数も少なくとてもシンプルに済んでくれて感動しました。これを、php artsian serve の npm run watchでホットリロードな開発も楽々。
難しいのはSPAであり、Reactではない、というのは常々思うところなのですが、React+Reduxの構成を作るめんどくささ、メンテするWebpackの設定については、やっぱりポイントポイントでつらみを感じてしまいます。
現在の仕事場で、サーバーサイドの開発者が片手間でVueをいじってちょっとした管理画面を作っている状況は、とても正解な気がしています。手軽さというのは大きなメリットですよね。ちなみにそれは、自分が今構築したものと同プロジェクトにあるもので、bladeがべったりのSPAでもないのですが、それも管理画面ですしね、豪華である必要もないでしょう。喜んでくれる人がいるかもしれませんが。
とりあえずいれとくかの気持ち
あと、大きなプロジェクトではないので、Vuex入れるべきかも考えましたが、実際ちょっと触った印象では、冗長ではありますが、入れる入れないで何か開発コストが上がるだとか、複雑性が増すとかそういうことでもなかったので、入れておきました。propsのバケツリレーのうざさやデバッグツールの強みなんかもReduxで存分に理解しているつもりですし。
ただ、Reduxを想定してる時とはちょっと導入については意識に差があります。何でしょう。正体が掴めたら言語化して起きたいです。
TypeScriptは入れたいけど、もう少しVue自体に慣れてからにします。