WebフレームワークでWebpackを使ってみよう〜Rails+Webpack+Vue.js編〜
第3弾はRailsです
Laravel、Djangoに続きRailsでWebpackを使ってみようと思います
作るものはお約束のこれです
jp.vuejs.org
環境
nodeやWebpackは今までと同じなので省略します
ただ、今までと違うのは yarn
が必要になります
Railsアプリの作成
まずはRailsアプリを新規作成します
rails new rails-webpack-vue
Gemfileに以下を追加し、インストールを行っていきます
gem 'webpacker', github: 'rails/webpacker'
bundle install rails webpacker:install rails webpacker:install:vue
コントローラー・画面の作成
新しいコントローラーを作成します
作られたコントローラーはそのままで問題ありません
rails g controller App index
config/routes.rb
にrootページを指定します
Rails.application.routes.draw do root to: 'app#index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end
サンプル機能を組み込んでいきます
まずはメインテンプレートhtmlにコンパイルされたJavaScriptを読み込むように追記します
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <title>RailsWebpackVue</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <%= yield %> <%= javascript_pack_tag 'hello_vue' %> </body> </html>
<%= javascript_pack_tag 'hello_vue' %>
を追記しました
以下はサンプルのままなので特に説明はありませんがご了承ください
app/views/app/index.html.erb
<!-- item template --> <script type="text/x-template" id="item-template"> <li> <div :class="{bold: isFolder}" @click="toggle" @dblclick="changeType"> {{ model.name }} <span v-if="isFolder">[{{ open ? '-' : '+' }}]</span> </div> <ul v-show="open" v-if="isFolder"> <item class="item" v-for="(model, index) in model.children" :key="index" :model="model"> </item> <li class="add" @click="addChild">+</li> </ul> </li> </script> <p>(You can double click on an item to turn it into a folder.)</p> <!-- the demo root element --> <ul id="demo"> <item class="item" :model="treeData"> </item> </ul>
app/javascript/packs/hello_vue.js
import Vue from 'vue' // demo data var data = { name: 'My Tree', children: [ { name: 'hello' }, { name: 'wat' }, { name: 'child folder', children: [ { name: 'child folder', children: [ { name: 'hello' }, { name: 'wat' } ] }, { name: 'hello' }, { name: 'wat' }, { name: 'child folder', children: [ { name: 'hello' }, { name: 'wat' } ] } ] } ] } // define the item component Vue.component('item', { template: '#item-template', props: { model: Object }, data: function () { return { open: false } }, computed: { isFolder: function () { return this.model.children && this.model.children.length } }, methods: { toggle: function () { if (this.isFolder) { this.open = !this.open } }, changeType: function () { if (!this.isFolder) { Vue.set(this.model, 'children', []) this.addChild() this.open = true } }, addChild: function () { this.model.children.push({ name: 'new stuff' }) } } }) // boot up the demo var demo = new Vue({ el: '#demo', data: { treeData: data } })
app/assets/stylesheets/app.scss
body { font-family: Menlo, Consolas, monospace; color: #444; } .item { cursor: pointer; } .bold { font-weight: bold; } ul { padding-left: 1em; line-height: 1.5em; list-style-type: dot; }
動作確認
コンパイルを行ってhttp://localhost:3000/にアクセスし動くか確認をします
bin/webpack rails s
...動かない
ブラウザのConsoleログを確認してみると
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
といったエラーがでています
これをぐぐってみると解決方法がQiitaにありました
この記事の方法を試すと無事動きました!
まとめ
Rails特有?の問題も発生しフレームワークの違いがでてきました
3つともWebpackのモジュールが用意されているので簡単に組み込むことができてハマるポイントは少ないように感じました
次は Spring Boot
でWebpackを試してみようと思います
今回も作ったソースは一式GitHubに上げてあります