emberのfastbootについて調べた
前からちょっと気になっていたのだけど、時間がとれたので調べてみました。
↓の動画で説明されてます。
vimeo.com
fastbootとは、emberが用意しているSSR(サーバーサイドレンダリング)の仕組みで、nodejsでemberアプリを動かしている。
つまり、サーバサイドアプリとemberアプリはそれぞれ独立しているのが前提。
たとえば、Railsでwebアプリを作っていた場合、fastbootを利用するには、unicornなどのアプリケーションサーバとは別にnodejsが必要です。
jQueryなど、ブラウザのAPIに依存した処理があると、当然エラーになります。($.ajax('xxxx')みたいな)
ember-networkのようにemberがplolyfilを用意していて、ここは開発者が気を付けて開発する必要あり。
あと、クライアントMVCのSSRで気になるのは、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を継承してるって知ってれば一瞬で解決できるんだろうけど、なかなか難しい
バージョン指定してgemを実行
gem _#{バージョン}_ rails
とすればよかった
再開したい
気づいたら1年放置してた。。
手元のメモ帳に書いて捨てるくせがなかなか消えないなー
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のコンフリクト起きてたのですが見なかったことにしました。
(また今度時間あるときに解決する。。)