Laravel + Vue look like SPA
2019-02-11
Server-side apps with client-side rendering - Jonathan Reinink
- blade 템플릿 + 각 기능별 vue 컴포넌트 : 너무 난해짐
- 빈 html + 1개의 단일 vue 컴포넌트 : api가 많아짐
- vue 컴포넌트 모두 등록후 controller에서 response::make를 통해 app.blade.php에 사용할 컴포넌트 이름과 데이타(props)를 넘겨 주는 방식 장점: API 없이 시작할 수 있다. 구조가 단순해진다.
// SPA처럼 작동하게 해준다.
npm install --save-dev turbolinks
// AppServiceProvider::boot 등록
use Illuminate\View\Factory as ViewFactory;
ViewFactory::macro('component', function ($name, $data = []) {
return View::make('app', ['name' => $name, 'data' => $data]);
});
<!-- app.blade.php -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="{{ mix('/css/app.css') }}" rel="stylesheet">
<script src="{{ mix('/js/manifest.js') }}" defer></script>
<script src="{{ mix('/js/vendor.js') }}" defer></script>
<script src="{{ mix('/js/app.js') }}" defer></script>
<meta name="turbolinks-cache-control" content="no-cache">
<!-- turbolinks 비활성화. 브라우저 이동시 vue 인스턴스를 만들어야함 -->
</head>
<body>
<div id="app" data-component="{{ $name }}" data-props="{{ json_encode($data) }}"></div>
</body>
</html>
// Controller
$events = Event::oldest('start_date')
->get()
->map->only('id', 'title', 'start_date');
return View::component('Events', ['events' => $events]);
// app.js
import Vue from 'vue'
// 모든 컴포넌트 등록
const files = require.context('./', true, /\.vue$/i)
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
// Start Turbolinks
require('turbolinks').start()
// Boot the Vue component
document.addEventListener('turbolinks:load', (event) => {
const root = document.getElementById('app')
if (window.vue) {
window.vue.$destroy(true)
}
//vue runtime만 사용
window.vue = new Vue({
render: h => h(
Vue.component(root.dataset.component), {
props: JSON.parse(root.dataset.props)
}
)
}).$mount(root)
})
//webpack.mix.js - vue runtime만 사용
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.extract(['vue', 'lodash', 'popper.js', 'axios'])
.webpackConfig({
resolve: {
alias: { 'vue$': 'vue/dist/vue.runtime.js' }
}
})
.version()