概要
薄いフレームワークとしてVue.jsが有名ですが、規模が大きくなると結局たいへんなことになってしまうので、設計が必要です。また、Railsでアプリケーションをつくる場合、Vue.jsのComponentチックな志向をうまく利用するのが一工夫必要かと思います。
そこで今回は、Vue.js on Railsを、中~大規模開発に耐えうる、かつ、RailsとVue.jsのメリットを両方活かせる設計を考えてみました。
「さくっとフレームワークを導入したい!」という方にはやや面倒かもしれませんが、逆に、この通りに作りさえすれば、あとはVue.jsなので、難解な概念が出てくることはありません(個人的には、少なくともこれくらい設計しないとフレームワークを導入する意味が無いのでは?・・・と感じますが)。最初だけ頑張れば、あとは楽ですし、jQueryもそのまま動きます。
※SPAなどではない、通常のRailsアプリケーションを想定しています
※Vue.jsの詳しい使い方はこの記事では紹介しません。
参考
ディレクトリ構成
先にディレクトリ構成を示しておきます。アプリケーションのルートにfrontend
ディレクトリを作り、その中に以下の様な構成でファイルを作成します(node_modulesは省略)。
├── bower.json
├── gulpfile.js
├── package.json
└── src
├── app.coffee # 「app.~」をWebpackでapp/assets/javascriptにbundleすればよいようにJSを書く
├── app.movie.coffee # 「app.~」をWebpackでapp/assets/javascriptにbundleすればよいようにJSを書く。movieページで読み込むJS例
├── utils # 共通メソッド
├── components # 紐づくviewが存在するcomponent http://vuejs.org/guide/components.html
├── filters # フィルター http://vuejs.org/guide/custom-filter.html
└── viewmodels # 基本的なscriptはすべてviewmodelで作成 http://vuejs.org/guide/index.html#ViewModel
モジュール管理
Vue.jsにはAngularJsのようなモジュール管理の仕組みはないので、BrowserifyかWebpackをつかいます。
できることに大差はないのですが、今回はWebpackを使いました。
Webpackだと、吐き出すファイルを複数にするのが容易なので、各ページごとにJSをつくることができます。また、プラグイン等入れなくても全部のせな感じなので、のちのちのことを考えるとこちらかな、という理由です。
参考
- uu59のメモ | browserifyとwebpack
- gulp.jsを使ってフロントエンドのビルドをする【webpack, stylus】 - yutaponのブログ
- optimization
- How to use webpack with Rails | clarkdave.net - assets/javascriptはgitignoreするなど。
Componentsのつくりかた
Railsのviewを活かしつつ、Componentをどのようにつくっていくかについて。まず、大きく分けて2つの方法があります。
方法
1.vueifyをつかって、".vueファイル(style, slim, jsがまとまったもの)"をcomponentにする
- Railsのviewファイルがあるにもかかわらずこれを使うのは相性が悪く、かなり工数を踏みそう。
- 現実的に難しい部分がある。
2.viewはRailsにpartialとしてつくり、componentのjsだけつくる。
- view側では、v-属性やidを指定し、特定要素にのみスクリプトが走るようなJSをかく。
- Railsチックにはなるが、SEOやレンダリングのことを考えるとこれ以上にベストな方法がなさそう。
結論
2を採用。
参考
ユニットテスト
方法
1.CommonJS pre-processorを用いてKarmaを使う。
- サーバーサイドのテストをCapybaraでかいてあるため、mockを再び書くこととかがでてきてしまう。
- 全体としてコード量が増える
2.RailsのCapybaraに統一する。
- フロントエンドエンジニアがCapybaraを書く必要が出てくる。
結論
2を採用。
タスクランナー
Gulpを採用。
パッケージ管理
npmを採用。
Rails側には、bundleしたjsを読み込ませるだけにしたかったので、フロントのライブラリ管理のみgemは用いず、npmで管理します。また、WebpackでNodeモジュールを呼び出すのを基本想定としているため、Bowerは使用しません。フォルダ構成などは、以下の記事が詳しいです。
サーバーとの通信
API通信をどうするかですが、デメリットはないので、superagentを採用。
共通処理
AngularJsでいうサービスをどう作るかについてです。
これは、Vue.jsではComponentとDirectiveしかないので、utilsフォルダをつくり、その中に、以下の様なmoduleをWebpackでつくることで対応しています。
module.exports = {
open: (elm) ->
target = elm.attr("href");
$(".modal"+ target).fadeIn("fast");
return false;
close: (elm) ->
elm.parents(".modal").fadeOut("fast");
return false;
}
呼び出しは以下のように。
utilModal = require('./../utils/modal')
module.exports = {
el: '#test'
methods: {
modalOpen: (e) ->
utilModal.open($(e.toElement))
modalClose: (e) ->
utilModal.close($(e.toElement))
}
}
参考
まとめ
ご意見ください。