koukiblog

たぶんweb系の話題

emberのfastbootについて調べた

前からちょっと気になっていたのだけど、時間がとれたので調べてみました。
↓の動画で説明されてます。
vimeo.com

fastbootとは、emberが用意しているSSR(サーバーサイドレンダリング)の仕組みで、nodejsでemberアプリを動かしている。

つまり、サーバサイドアプリとemberアプリはそれぞれ独立しているのが前提。
たとえば、Railsでwebアプリを作っていた場合、fastbootを利用するには、unicornなどのアプリケーションサーバとは別にnodejsが必要です。

jQueryなど、ブラウザのAPIに依存した処理があると、当然エラーになります。($.ajax('xxxx')みたいな)
ember-networkのようにemberがplolyfilを用意していて、ここは開発者が気を付けて開発する必要あり。

あと、クライアントMVCSSRで気になるのは、DOMの生成ですが、
emberの場合は、htmlbarsというemberで利用しているテンプレートエンジンがhtmlのサブセットを理解できて、それを利用しています。
HTMLBars: The Next-Generation of Templating in Ember.js

手元で確認してみたところ

<div>
<span>welcome to ember</span>
<div>
  {{outlet}}
</div>

がfastboot用にビルドを行ったところ

    buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        var el1 = dom.createElement("div");
        var el2 = dom.createTextNode("\n");
        dom.appendChild(el1, el2);
        var el2 = dom.createElement("span");
        var el3 = dom.createTextNode("welcome to ember");
        dom.appendChild(el2, el3);
        dom.appendChild(el1, el2);
        var el2 = dom.createTextNode("\n");
        dom.appendChild(el1, el2);
        var el2 = dom.createElement("div");
        var el3 = dom.createTextNode("\n  ");
        dom.appendChild(el2, el3);
        var el3 = dom.createComment("");
        dom.appendChild(el2, el3);
        var el3 = dom.createTextNode("\n");
        dom.appendChild(el2, el3);
        dom.appendChild(el1, el2);
        var el2 = dom.createTextNode("\n\n");
         dom.appendChild(el1, el2);
        dom.appendChild(el0, el1);
        var el1 = dom.createTextNode("\n");
        dom.appendChild(el0, el1);
        return el0;
      }

に変換されていました。
ReactとJSXの関係に近いですね。JSXは結構制約が強いイメージだったけど、htmlbarsは自由度高そうな雰囲気。

webのフロントエンドは日々複雑になっているし、スマホアプリにAPIを提供するみたいに、サーバーサイドアプリはAPIに徹して、webのフロントエンドはクライアントMVC(SSR出来ればなおよし)で構築するのもよいんじゃないかなという気もしてきました。

emberそんなに悪くないと思うんだけど、日本語リソースが少ないのが気になるところ。
複雑なwebアプリ作るときには結構現実的な選択肢だと思うんですけどね。

Railsのforce_sslの判定方法

Railsのforce_sslがどうやってSSLかどうか見分けてるかわからなくて調べたときのメモ

https://github.com/rails/rails/blob/3d70f0740b26b0a137d7e6436f9909330f8ee888/actionpack/lib/action_controller/metal/force_ssl.rb#L76
ここまでは簡単に辿り着けるんだけど、このrequest.ssl? が何をしているのかがわからない。。


Diving in Rails - The request handling
rails request soruceとかでぐぐって見つけた記事を読むと
requestが、ActionDispatch::Requestなことがわかる

rails/request.rb at e595d91ac2c07371b441f8b04781e7c03ac44135 · rails/rails · GitHub
ActionDispatch::Reqeustを見てみる。けど、ここにもssl? はいない。けどRack::Requestを継承していることがわかる。

rack/request.rb at master · rack/rack · GitHub
Rack::Requestを見てみると、やっとssl? を発見。

if @env[HTTPS] == 'on'
'https'
elsif @env[HTTP_X_FORWARDED_SSL] == 'on'
'https'
elsif @env[HTTP_X_FORWARDED_SCHEME]
@env[HTTP_X_FORWARDED_SCHEME]
elsif @env[HTTP_X_FORWARDED_PROTO]
@env[HTTP_X_FORWARDED_PROTO].split(',')[0]
else
@env["rack.url_scheme"]
end

最終的な条件式はこれでした

Controllerから参照できるrequestは、AcitonDispatch::RequestでそれはRack::Requestを継承してるって知ってれば一瞬で解決できるんだろうけど、なかなか難しい

Asset PipelineのPreCompile対象とその設定

いつも忘れては調べて思い出して。。を繰り返していたのでいいかげん覚えようと思ってメモっておく

  • precompile対象のファイル

デフォルトでは
JS:
app/assets/application.js
CSS:
app/assets/application.css
となっている。

つまり、デフォルトの設定は、アプリケーションでjs,css共に1ファイルになるべきという考え方になっていて
どの画面でもコンパイル後のapplication.js,application.cssで動くようにしないといけない。
( // require_tree . がついてるので、コントローラー毎のJSを1ファイルに結合して使用する形になる)

気をつけないといけないのが、特定の画面で、特定のJSだけを読み込もうとして

 <%= javascript_include_tag params[:controller] %>  

みたいに書いていた場合、
production環境で実行すると、下記のようなエラーが発生して、レンダリングすら行われない

ActionView::Template::Error (XXXXXXX.js isn't precompiled):
    40:     <!-- Javascripts
    41:     ================================================== -->
    42:     <!-- Placed at the end of the document so the pages load faster -->
    43:     <%= javascript_include_tag params[:controller] %>
    44:   </body>
    45: </html>

前述の通り、コンパイルされるのは、application.jsだけなので、production環境では、ファイルが見つからずエラーになる。

  • precompile対象の設定

設定を追加することで、precompile対象を追加することができる
/config/enviroments/production.rb内の

config.assets.precompile 

に追加でおk。

基本的には、JSは1ファイルにまとめても動くように作って、必要に応じて追加するのがよいのかな。
管理画面用のJSは別で切り出すとかありそうだし。

homebrewで入れたruby-buildを最新にする

brew upgrade --HEAD ruby-build

でokでした。

ふと brew update してみたら、gitのコンフリクト起きてたのですが見なかったことにしました。
(また今度時間あるときに解決する。。)

RSpecで常に--format documentation にする

アプリケーションルートに、.rpsec という名前でファイルを作成し、
ファイル内にデフォルトで使用したいオプションを記載すればok

--color
--format documentation

てしとくと、たいていの場合いいんじゃないのかな。

Railsの場合、rspec-railsrspec:installで、.rpsecファイルは作成されてるみたいです。