Rails4 + TypeScript + AngularJS + slimで 快適開発環境構築!最短でSPA環境作成。
2016.02.20
この記事は最終更新日から1年以上が経過しています。
最近は何かと、iphoneアプリにはまってまして、久々にwebの方も書こうかと。
いやぁ。しかしRailsは便利ですね。
何かと話題のRuby on Rails。
Ruby on Railsを利用すると、サクッと、DBや、webサービスも作れるし、前に比べるとwebサービスなどの制作の敷居も下がったのではないかと。
しかしながら、Ruby on Railsのデフォルトで用意された、view helperやcoffeescriptでフロントを作成しようとすると、どうもインタラクティブなUIを作ろうとしても、効率が悪かったり、やや強引な設計になったりしませんか。
という事で、RailsにはAPIを返すだけ(極端に言うと)にし、フロントエンド(viewの作成)はAngularJSを用いてSPA化し、TypeScriptでより保守性を高め快適な開発環境を構築しようではないですか。
(何かと、TypeScript +AngularJSが鉄板化して来てる感じ。)
といった感じで、図で書くと以下の様な設計になります。
こうなっているのを
新たにこうしていきます。
開発環境
Rails 4.2.4
angularjs-rails 1.4.8
typescript-rails 0.5.0
slim-rails 3.0.1
TypeScript
まず最初にTypeScript。
TypeScriptは所謂、AltJSの一つで、2016年のAltJSトレンドランキングでぶっちぎりの1位を進んでいますので、多くの方が利用されているかと思います。
参考URL
http://www.buildinsider.net/web/popularjslib/2016
RailsでもTypeScriptを使いたい!!
TypeScriptに慣れている方はやはりそう思いますよね。。
安心してください。履いています。
typescript-railsなるものがきちんとありますので、Ruby on Railsでも問題なく、TypeScriptは使えます。
github
https://github.com/typescript-ruby/typescript-rails
日本人のFUJI Goroさんがメンテナーとして活動されていますので、是非頑張っていただきたいです><
こちらをgemfileに追加しましょう。
gem 'typescript-rails' '~> 0.5.0'
bundle install
ファイル作成
TypeScriptのファイル作成に関しては、「◯◯.js.tsファイル」を作成する事によってtsファイルが自動で読み込まれ、JavaScriptファイルにコンパイルされます。
app/assets/javascripts/◯◯.js.ts
module Hoge { class HogeModel { public hoge:string = "hoge"; } }
rails s で、railsサーバーを起動するとJavaScriptファイルにコンパイルされています。
コンパイル後
var Hoge; (function (Hoge) { var HogeModel = (function () { function HogeModel() { this.hoge = "hoge"; } return HogeModel; })(); })(Hoge || (Hoge = {}));
言うまでもないかも知れませんが、TypeScriptは静的型付け言語です。
なので、定義なしのその他のJavaScriptライブラリのオブジェクト等をTypeScript内で利用しようとするとコンパイルエラーが発生し、コンパイルを行うことが出来ません。
その際は、以下からライブラリに適した定義ファイルをダウンロードし、、プロジェクトに定義ファイルを追加しましょう。
大概のものはこちらで揃います。
github
https://github.com/DefinitelyTyped/DefinitelyTyped
jqueryを使おうとしても、定義ファイルを読み込んでいない状態だとエラーで画面すらも表示してくれませんね。
reference pathに追加しましょう。
/// <reference path="typings/jquery.d.ts" />
これで、reference pathを追加した、TypeScript内でjqueryも利用できる様になります。
TypeScriptを用いることによって、コンパイル前にエラーが出ますので、より強固なフロントとなりますので、フロントエンドの保守性を高めていきましょう。
AngularJS
こちらも説明は不要かもしれませんが、AngularJSはMVVMフレームワークでこちらも、トレンドランキングでぶっちぎりの1位を進んでいますので、多くの方が利用されているのでしょう。
参考URL
http://www.buildinsider.net/web/popularjslib/2016
AngularJSは、バージョン2もベータではありますが、配布されていて、そちらを使っても良いのですが、今までとは記述など全く異なり、別フレームワークになっている印象ありなので、1.4.8を利用します。
最近、1.5がリリースされましたが、とりあえず1.4.8で。
ダウンロードして読み込むのもいいのですが、Rails wayの沿って、こちらもGemfileに追加するのが良いでしょう。
gem 'angularjs-rails'
bundle install
app/assets/javascripts/application.js にrequireで追加。
app/assets/javascripts/application.js
//= require angular
rails s でrailsサーバーを起動。
これでもうAngularJSが利用できます。
Railsだから記述が異なる。って事は無いのですが、viewテンプレートに「Haml」や「Slim」などを利用していると記述の仕方に戸惑いますよね。(自分だけかな)
haml
%div{'ng-controller' => 'MainCtrl'} %ul %li{'ng-repeat' => 'item in items track by $index'} {{item}}
slim
div ng-controller = 'MainCtrl' ul li ng-repeat = 'item in items track by $index' | {{item}}
そうでもないか。
属性も含めようとすると、こんな感じになりますかね。
slim
li*{:draggable => :true} ng-repeat="item in itemList track by $index"
また、slimで値のないディレクティブを作成しようとすると、おかしな事になりますので空文字を与えると良いかと思います。
slim
div hoge
これだとさすがにダメですので、
div hoge=""
とするか、
.div*{ 'hoge' => '' }
で、ディレクティブの定義は行えるかと思います。
Rails
最後はRais側。
アセットパイプライン(Asset Pipeline)
Railsのアセットパイプライン(Asset Pipeline)は非常に便利である。
app/assetsフォルダ配下にあるCSSとJavaScriptを全てまとめて圧縮し、それぞれ application_xxxxx.css、application_xxxxx.jsファイルを作成してくれるのだが、時にはそれが余計なお節介に感じることもある。
マニフェストファイルである、application.jsに
//= require_tree .
と記述すると、作成したjsファイルを全て結合してくれるのですが、当然全て結合されてしまいますので、色々と問題発生しますよね。
ネームスペースが衝突したり、読み込みが莫大になったりと。。
という事で、コントローラのアクション単位で読み込みたいなと思いまして、layouts/application.html.hamlでは以下の様にRailsのコントローラ名に沿ってディレクトリを作成し、アクション名のファイルを読み込む様にしました。
layouts/application.html.haml
= javascript_include_tag controller.controller_name + '/' + controller.action_name, "data-turbolinks-track" => true
コントローラ単位でディレクトリを区切り、アクションとjsファイルは対に作成することにし、config/initializersに記述することでassetprecompileで読み込まれ、JavaScriptファイルもコントローラのアクション毎に読み込まれる様になりますね。
config/initializers
Rails.application.config.assets.precompile += %w( controller_name/action_name.js )
JavaScript(TypeScript)を作成する度に追加する必要がありますが、Rails以外でheadの追加する感覚だと思っていただければと。
API
最後はRuby on Rails側でのAPI。
ユーザーが最初にページに訪れた時に、ページ読み込こんだ後に、JavaScriptを読み込んでRailsの方にApiを投げて帰って来たJSONデータでレンダリング。
とやっていると、初期のページレンダリングが遅くなりますね。
図で書くと以下の様な感じです。
さすがに厳しいので、ページレンダリングと同時にレンダリングに必要なJSONを渡す形にする事によってより快適になります。
方法は至ってシンプルで、Rilas側で、JSONのインスタンス変数を作成し view側に渡します。
@hoge = { name: "たかやま" }.to_json
(今回は例として、nameがキーとなったJSONデータのみ。本来はきちんと作成)
後は、view側で受け取りAngular側に渡す事によって無駄なリクエストは減ります。
この際に、「’」や「タブ」「スペース」などの削除処理、XSS対策は適切に行っておきましょう。
ページ表示後は、それぞれに応じたAPIを叩く事によって、SPA化が行えます。
と、RailsをAPI専用にする事によって、Rails側では、API作成用に精査され、フロント側では、インタラクティブなUIの作成が出来、よりリッチなSPAのコンテンツ作成する事ができるかと思います。
参考になればとー。ではでは。