在HAML模板中使用:coffescriptfilter的性能影响?
所以HAML 4包含一个coffeescriptfilter ,它允许我们喜欢咖啡的人们做这样的整洁的事情:
- word = "Awesome." :coffeescript $ -> alert "No semicolons! #{word}"
我的问题:对于最终用户来说,这比使用等效的:javascript
filter慢吗? 使用coffeescriptfilter是否意味着coffeescript将在每次加载页面时编译为javascript(这显然会造成性能灾难),或者这只会在应用程序启动时发生一次?
这取决于。
当Haml编译filter时,它会检查filter文本是否包含任何插值 ( #{...}
)。 如果没有,则每个请求都将转换相同的文本,因此转换在编译时完成一次,结果包含在模板中。
如果filter文本中有插值,那么要转换的实际文本将因每个请求而异,因此每次都需要编译Coffeescript。
这是一个例子。 首先没有插值:
:coffeescript $ -> alert "No semicolons! Awesome"
这会生成代码(使用haml -d
来查看生成的Ruby代码):
_hamlout.buffer << "\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
filter中没有任何插值。
:javascript
filter的行为类似,检查是否有任何插值,但由于:javascript
filter仅在运行时向缓冲区输出一些文本,因此使用它的性能损失要小得多。 您可以组合:javascript
和:coffeescript
filter,将插值数据放入:javascript
并保持:coffeescript
static:
- word = "Awesome" :javascript var message = "No semicolons! #{word}"; :coffeescript alert message
亚特的答案清楚地表明发生了什么。 我帮助将locals添加到:coffeescript
来自哈希的:coffeescript
filter。 这样您就不需要使用全局JavaScript变量。 作为旁注:在Linux上,减速实际上可以忽略不计。 但是在Windows上,对性能的影响非常重要(每个块编译容易超过100ms)。
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'])
由于没有interpollation,代码实际上是正常编译的。