tl;dr
- Railsの部分テンプレート中にjavascript埋め込みたい
- でもページ途中に
<script>
入れると、パフォーマンス落ちる - async属性使えばいいんじゃね
kwsk
Railsを使っていて、Viewの途中にjavascriptを入れたくなることが結構あります。
たとえば部分テンプレートを使ったり、Cellsなんかを使って、
- controllerやmodel的な処理
- html構造
- javascriptでの画面動作
を一つにまとめておきたい、という感じで。
app/cells/cart_cell.rb
class CartCell < Cell::Rails
def show(args)
user = args[:user]
@items = user.items_in_cart
render # renders show.html.haml
end
end
app/cells/cart/show.html.haml
#cart
You select #{@item.size} items.
%ul
- @items.each do |item|
%li= item.name
= javascript_include_tag "cart/list_lazy_load"
最後の行でapp/view/assets/cart/list_lazy_load.js.coffee
あたりを呼び出し、適当な機能を画面につけています。
問題なのが、bodyの途中に<script>
タグがあるとブラウザが以下のように動作をするということ。
<p>content 1 ...</p> <!-- ブラウザによるレンダリング -->
<script src='sleep100.js'></script>
<!-- sleep100.jsの実行が終わるまでレンダリングをブロック -->
<p>content 2 ...</p> <!-- ブラウザによるレンダリングの続き -->
この現象を回避するために「<script>
はheadの中かbodyの一番最後に書く」というテクニックを使うのがHTMLの常套手段です。
スクリプトファイルの中にコストのある処理(jQueryを使ったすごいやつとか)がある場合、低スペックマシンではページ全体の印象がもっさりとしてしまいます。
ってわけで、<script>
にasync属性を指定して、裏で実行するようにしましょう。
app/cells/cart/show.html.haml
:
= javascript_include_tag "cart/list_lazy_load", async: 'async'
これでjavascriptの実行を待たずに、HTMLページのレンダリングをしてくれるようになりました。
参考
とても参考になりました
scriptのdefer/asyncを理解し、ページの高速化方法を探る - ゆっくりと…
┗ defer/asyncチェックツールを作りブラウザ対応状況を確認してみた 2010/12/4