我想知道如何缓解用户通过AJAX与您的网站交互时出现的问题,同时部署新版本的网站。
想象一下这样的场景:
用户通过单击"下一步"按钮浏览您的帖子。这个"下一步"按钮通过XHR向服务器提交一个表单,然后服务器用服务器生成的Javascript响应(SJR(进行响应。
SJR呈现此Javascript:
// in create.js.erb
renderNewPost(<%= @post.to_json %>);
(renderNewPost
在级联的、缩小的application.js
中定义,并由用户的浏览器缓存。(
目前一切都很顺利。
现在,作为一个新功能的一部分,您将端点的SJR更改为首先记录一些内容:
// in create.js.erb
logSomething("hi!");
renderNewPost(<%= @post.to_json %>);
并将函数logSomething
添加到您的application.js
中。
用户再次单击"下一步"按钮。这一次,SJR用logSomething('hi')
线路进行响应。。。但是浏览器没有在任何地方定义logSomething
,因为浏览器加载的application.js
是第一个版本。
现在,在刷新页面之前,用户将无法使用您的网站。
我们如何解决这个问题?手头的问题有名字吗?
选项1:
一个简单的选择是,让响应尽可能独立,这意味着在您的示例中,您不会在其他地方定义log_something
方法,而是在同一响应中定义。
选项2:
另一种可能更通用的解决方案是,在应用程序控制器中的自定义响应标头(比如X-SJR-Version
(中发送某种版本
before_action do
response.headers['X-SJR-Version'] = '1.0.0'
end
并添加一些Javascript客户端代码,在其中执行AJAX请求,检查版本是否仍然匹配。一个粗略的实现可能是这样的(虽然未经测试(:
var version = null;
$(document).bind("ajaxSuccess", function(xhr, status){
var newVersion = xhr.getResponseHeader('X-SJR-Version')
if(version === null) { version = newVersion } // initial version
if(newVersion !== version) { location.reload(); }
});
这就利用了jquery钩子ajaxSuccess来执行版本检查。如果您正在使用常规的jquery ujs rails调用,您可能需要检查此页面。
现代方法:
然而,现代轨道应用程序通常不再使用服务器生成的javascript,因为那里的架构通常是自己编写客户端javascript(通常使用react、angular或vue(,并为来自服务器的数据使用JSON API端点,而javascript代码已经存在于页面的响应中,并且不需要加载额外的JS。
这样做的优点是,您可以使用API-version,而加载的javascript将坚持旧版本,因此您可以平稳地转换到较新的API版本(而通常您甚至不需要新的API版本,因为只有javascript会更改(
因此,你很可能找不到这个问题的开箱即用的解决方案,而不得不采取类似上述的措施。