vue + vuex + vue-router のwebpackなしサンプル(コピペでできる)
問題
webpackとかLaravelなしで vue+vuex+vue-routerできないですか。

答え
htmlファイル1個と、jsファイル1個で、小さなSPA(Single Page Application)っぽいことをしてみる。
ファイル構成は以下のみ。
. |-- index.html `-- app.js
vue, vuex, vue-router はCDNから読み込めばOK(もちろんローカルにダウンロードして使ってもOK)。
jsはhtmlの中に <script>~</script> で書いても構わないけど、一応分けた。
HTML(index.html)
SPAでよく見る <div id="app"></div> しかないHTML。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>vue + vue-router + vuex</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
<script defer src="app.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
スタイルシートはBootstrap4を入れた。
自前のCSSファイルがあれば追加で読み込んでよい。
es6-promise.auto.js はIE対策。Promiseのないブラウザ対策。不要なら削除してもよい。
JavaScript(app.js)
1つのファイルにすべてを書く。
- vue-routerに呼び出してもらうコンポーネント定義(Home、Foo、Bar)
- ルート定義(route)
- VueRouter作成(router)
- Vuexのストア作成(store)
- Appとヘッダー(Navigation)、フッター(Footer)の子コンポーネント作成
- 最後に new Vue({el: '#app'})
- Vueにstoreとrouterを持たせることで、子コンポーネントたちも this.$store で参照できる
const Home ={
template: '<div>Homeです。</div>'
}
const Foo ={
template: '<div><p>Foo画面です</p>'
+ '<button class="btn btn-info" v-on:click="$store.commit(\'increment\')">クリックするとカウンターが増えます {{ count }}回目</button></div>',
computed: {
count: function () {
return this.$store.state.count
}
}
}
const Bar ={
template: '<div><p>Bar画面です</p>'
+ '<button class="btn btn-success" v-on:click="$store.commit(\'increment\')">クリックするとカウンターが増えます {{ count }}回目</button></div>',
computed: {
count: function () {
return this.$store.state.count
}
}
}
const routes = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
const router = new VueRouter({
routes: routes
})
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
});
const Navigation ={
template: '<nav class="nav bg-light mb-3">'
+ '<router-link to="/" class="nav-link">Home</router-link>'
+ '<router-link to="/foo" class="nav-link">Foo</router-link>'
+ '<router-link to="/bar" class="nav-link">Bar</router-link>'
+ '</nav>'
}
const Footer ={
template: '<footer class="fixed-bottom bg-light p-3">フッター</footer>',
}
const App ={
template: '<div><Navigation/><div class="container-fluid"><router-view/></div><Footer/></div>',
components: {
Navigation: Navigation,
Footer: Footer
},
computed: {
count () {
return this.$store.state.count
}
}
}
new Vue({
el: '#app',
router: router,
store: store,
template: '<App/>',
components: {
App: App
}
});
ES6では以下のように短縮して書かれていることが多いですが、
components: {
Navigation,
Footer
},
JSONっぽいこちらの書き方で書いてます。
components: {
Navigation: Navigation,
Footer: Footer
},
結果
ちゃんとちょっとしたSPAらしい動きをする。

次は
node.js、npm、composer、Laravelなどに一切触れなくてもここまではできました。
こうしてみると課題が見えてきます。
- テンプレートが書きにくい
- このまま1ファイルに書き続けるのはつらい
- 大規模なものになると必要に応じてコンポーネントを遅延ロードする仕組みにしたくなる
結局webpack導入となるわけですね。