10

そのため、HAML 4 には coffeescript フィルターが含まれており、これにより、コーヒーを愛するレールの人々は次のような素晴らしいことを行うことができます。

- word = "Awesome."

:coffeescript
  $ ->
    alert "No semicolons! #{word}"

私の質問: エンド ユーザーにとって、これは同等の:javascriptフィルターを使用するよりも遅いですか? coffeescript フィルターを使用すると、ページが読み込まれるたびに coffeescript が javascript にコンパイルされる (明らかにパフォーマンスが低下する) ことになりますか? それとも、アプリケーションの起動時に 1 回だけ発生するのでしょうか?

4

2 に答える 2

15

場合によります。

Haml がフィルターをコンパイルするとき、フィルター テキストに補間( #{...}) が含まれているかどうかを確認します。何もない場合、各リクエストで変換するのは同じテキストになるため、変換はコンパイル時に 1 回行われ、結果がテンプレートに含まれます。

フィルタ テキストに補間がある場合、変換する実際のテキストはリクエストごとに異なるため、毎回 Coffeescript をコンパイルする必要があります。

例を次に示します。最初の補間なし:

:coffeescript
  $ ->
    alert "No semicolons! Awesome"

これにより、コードが生成されます (haml -d生成された Ruby コードを確認するために使用します)。

_hamlout.buffer << "<script>\n  (function() {\n    $(function() {\n      return alert(\"No semicolons! Awesome\");\n    });\n  \n  }).call(this);\n</script>\n";

このコードは単に文字列をバッファに追加するだけなので、Coffeescript は再コンパイルされません。

今補間で:

- word = "Awesome."

:coffeescript
  $ ->
    alert "No semicolons! #{word}"

これにより、次が生成されます。

 word = "Awesome."
_hamlout.buffer << "#{
find_and_preserve(Haml::Filters::Coffee.render_with_options(
"$ ->
  alert \"No semicolons! #{word}\"\n", _hamlout.options))
}\n";

ここで、Haml は補間の値が何であるかを確認するのを待つ必要があるため、Coffeescript は毎回再コンパイルされます。

フィルター内に補間を持たないことで、リクエストごとに Coffeescript をコンパイルすることを避けることができます:coffeescript

:javascriptフィルターは同様に動作し、補間があるかどうかを確認しますが、フィルター:javascriptは実行時に一部のテキストのみをバッファーに出力するため、それを使用した場合のパフォーマンス ヒットははるかに少なくなります。組み合わせ:javascript:coffeescriptフィルタリングし、補間されたデータを入れて静的:javascriptに保つことができます。:coffeescript

- word = "Awesome"

:javascript
  var message = "No semicolons! #{word}";

:coffeescript
  alert message
于 2013-07-10T12:57:05.583 に答える
4

何が起こっているのかについてのマットの答えは明らかです。:coffeescriptハッシュからフィルターにローカルを追加するヘル​​パーを作成しました。これにより、グローバルな JavaScript 変数を使用する必要がなくなります。補足として、Linux では、速度低下はごくわずかです。ただし、Windows では、パフォーマンスへの影響は非常に重要です (コンパイルに 1 ブロックあたり 100 ミリ秒以上かかります)。

module HamlHelper
  def coffee_with_locals locals={}, &block
    block_content = capture_haml do
      block.call
    end

    return block_content if locals.blank?

    javascript_locals = "\nvar "
    javascript_locals << locals.map{ |key, value| j(key.to_s) + ' = ' + value.to_json.gsub('</', '<\/') }.join(",\n    ")
    javascript_locals << ";\n"

    content_node = Nokogiri::HTML::DocumentFragment.parse(block_content)
    content_node.search('script').each do |script_tag|
      # This will match the '(function() {' at the start of coffeescript's compiled code
      split_coffee = script_tag.content.partition(/\(\s*function\s*\(\s*\)\s*\{/)
      script_tag.content = split_coffee[0] + split_coffee[1] +  javascript_locals + split_coffee[2]
    end

    content_node.to_s.html_safe
  end
end

これにより、次のことが可能になります。

= coffee_with_locals "test" => "hello ", :something => ["monde", "mundo", "world"], :signs => {:interogation => "?", :exclamation => "!"} do
  :coffeescript
    alert(test + something[2] + signs['exclamation'])

補間がないため、コードは実際には通常どおりコンパイルされます。

于 2013-10-21T18:10:54.603 に答える