如何处理调用浏览器尚无代码的 SJR 响应?



我想知道如何缓解用户通过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会更改(

因此,你很可能找不到这个问题的开箱即用的解决方案,而不得不采取类似上述的措施。

最新更新