Rails资产管道:如何防止特定资产的缓存

4

如标题所述,我想要防止特定资产的缓存,即JavaScript文件something.js.erb。情况如下:

something.js.erb的内容:

...
var something = <%= SomethingHelper.get_something.to_json %>;
...

它成功地绑定了SomethingHelper的值,但只有一次,除非手动编辑javascript文件,否则var something的值永远不会再次分配。

这可能是可以预料的,但显然不符合我的需求。根据调用时间,SomethingHelper.get_something的输出会发生变化。因此,我需要在编译的something.js文件中看到最新的数据。

我的确切需求:

  • 我不想完全禁用资产管道缓存
  • 我只希望每次请求something.js.erb时都会呈现。

这是否可能?

环境信息:

  • Rails 4
  • 开发模式
  • Rails自己的服务器,但将在生产环境中使用nginx

谢谢

2个回答

0

你正在将前端业务逻辑与数据结合在一起。这是不可取的,也是我不建议在大多数情况下使用ERB + JS(尤其是像Rails教程和指南中那样触发响应行为)的原因之一。你最好选择以下其中一种方式:

  1. 发送请求以从JavaScript中获取数据。
  2. 如果变量将在每个页面(或接近每个页面)上使用,并且是相对简短的非二进制数据,则可以在布局中嵌入具有相关信息的标签。

例如:

# /app/views/layouts/application.html.erb
<%= tag :meta, name: 'something', content: @something %>

# /app/assets/javascripts/application.js
$('meta[name="something"]').attr('content');

1- 没有数据,前端业务逻辑应该如何进行?从逻辑上讲,在HTML加载后通过AJAX获取数据和在编译时将数据绑定到js中没有区别。最终,在需要时js上下文中都可以使用数据。2- 数据量很大,这是我试图避免在dom准备就绪时进行初始AJAX的主要原因。 - destan
  1. 我并没有说逻辑操作不需要数据,你也不需要走向另一个极端。区别是相当显著的:关注点分离、客户端性能、不破坏你的架构等等。
  2. 特别是如果这是大量数据,你应该异步加载它(咳咳,AJAX),以免在此过程中阻止主线程响应。这样可以让客户端缓存JS以及数据,如果你在应用程序中设置了适当的HTTP缓存,而不是两者都不行。你还可以避免在每个请求JS时运行缩小。
- coreyward
换句话说,有一个既定的模式可以做到你想要的,并且它与你的架构非常匹配,但是你却遇到了障碍,因为你坚持采用一种非标准设计,这种设计除了可能会稍微减少一点代码之外并没有任何好处。 - coreyward
首先,感谢您的评论。好的,也许我没有表达清楚我的观点。数据相当大,页面需要呈现它,所以我不希望客户端浪费时间等待 AJAX 响应。此外,AJAX 将是一个(不必要的)额外调用,这将使服务器繁忙。因此,既然可以避免,我正在尝试避免它。然后你会问“为什么用 js 渲染页面,用 erb 渲染它”,这是另一个源自应用程序本质的“架构”要求。 - destan
我真的需要这个用法,最终在HTML中将数据放置在<scripts>标签之间。我猜这样做更加丑陋,并且数据需要在使用闭包等后从全局范围中清除。我真的希望能够直接动态地将Rails中的JSON绑定到JavaScript文件中。 - destan
根据我的经验,AJAX请求的开销很小,特别是与阻塞调用中加载数据相比。我相对自信地认为,你会发现缩小和资产指纹添加会给JS的渲染增加一些不可忽略的延迟。D3.js被构建来处理大量从AJAX请求中获取的数据,并将其呈现到DOM中(通常以相当复杂的方式)。我建议你花几个小时去理解他们这样做的如何和为什么。再次提醒你,我指向缓存来解决大部分性能问题。 - coreyward

0

我可以提供两个选项:

1)使用内联js设置变量:

<%= javascript_tag do %>
  window.something = '<%= j SomethingHelper.get_something.to_json %>';
<% end %>

2)将变量存储在您的HTML中,并从JS中调用:

#html

<body data-something="<%= j SomethingHelper.get_something.to_json %>">
</body>

#js

$("body").data("something");

使用内联js设置变量:我一开始就试图避免这种风格。将变量存储在HTML中并从JS中调用它,我认为这比第一个更丑陋:( - destan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接