I've custom pages for 404 and 500 errors using my default layout.
But when I'm rendering these pages with their proper status, Turbolinks seems to reevaluate all JS making things go south. With a 200 status on these pages, no problem...
After some debuging, I've seen than in 2xx case it goes through the SnapshotRenderer and in the other cases the ErrorRenderer.
What is the point of this ErrorRenderer ?
Wondering the same thing here with 403. Things don't go south but it causes a flash of unstyled content.
Demo:
Click on "Notification Settings" on https://thredded.org/thredded/.
I've personally solved my issue the dirty way, monkey patching Turbolink, waiting for a better understanding of this issue or eventually a fix.
# Monkey patch Turbolinks to render 404 & 500 normally
Turbolinks.HttpRequest.prototype.requestLoaded = ->
@endRequest =>
if 200 <= @xhr.status < 300 or @xhr.status = 404 or @xhr.status = 500
@delegate.requestCompletedWithResponse(@xhr.responseText, @xhr.getResponseHeader("Turbolinks-Location"))
else
@failed = true
@delegate.requestFailedWithStatusCode(@xhr.status, @xhr.responseText)
/cc @sstephenson
Ran into this today while upgrading from turbolinks 2.5.3 to 5.0.1. When using custom pages and rendering them with status: 404 or status: :not_found or any other status code it would cause JS issues that were hard to diagnose. Using above patch fixed the issues.
I've encountered the same issue, not only with custom pages but with error pages being rendered through a turbolinks request.
The patch above didn't fix the issues for me.
Here is a monkey-patch that also handles 403 and is in ES5 instead of CoffeeScript:
// Monkey patch Turbolinks to render 403, 404 & 500 normally
// See https://github.com/turbolinks/turbolinks/issues/179
window.Turbolinks.HttpRequest.prototype.requestLoaded = function() {
return this.endRequest(function() {
var code = this.xhr.status;
if (200 <= code && code < 300 ||
code === 403 || code === 404 || code === 500) {
this.delegate.requestCompletedWithResponse(
this.xhr.responseText,
this.xhr.getResponseHeader("Turbolinks-Location"));
} else {
this.failed = true;
this.delegate.requestFailedWithStatusCode(code, this.xhr.responseText);
}
}.bind(this));
};
I read code around visit.coffee, view.coffee and etc. to find this issue for our bug.
While I want to have custom header (e.g. Turbolinks-Force-Success: true) for avoid this, it'd also be better to be documented.
turbolinks-rails overwrites redirect_to to return custom header instead of 3xx response:
https://github.com/turbolinks/turbolinks-rails/blob/10fabf0e3885c63e9d6ea698f929a8c5ad491a73/lib/turbolinks/redirection.rb#L9
I prefer add render ..., turbolinks: true option and override status to 200 like above redirect_to does.
Above one was not good idea, manipulating response code can have bad influence on caching or etc.
I find it a little odd something like this hasn't been addressed already. I would've thought a good proportion of Rails apps would serve error pages using the default template.
@kochka I use your solution before I was getting some errors like rails_ujs already loaded but now, when I'm catch by a error page and click in browser's back button, my front end is all broken without styles.
Oh this solved my problem #277
I checked how Basecamp handles this themselves. After a 404 subsequent visits trigger a full page reload. Seems like a nice way to handle this situation.
Also, Turbolinks.ErrorRenderer seems to be extended with custom behaviour to render the error page.
Most helpful comment
Here is a monkey-patch that also handles 403 and is in ES5 instead of CoffeeScript: