Recently, I re-encountered an issue with how Firefox Prefetchs some content, specifically urls within a <link rel=’next’ header element. This isn’t the first time this has caused me to spend some time debugging what appears to be a weird bug in my code, so I decided to write a post describing the issue, how it affected me, and how to remove the ‘prev’ and ‘next’ elements from WordPress.
The rel=’next’ and rel=’prev’ links are meant as an indication of related pages and are added automatically by WordPress. I have typically thought of them more as an accessibility aid, like for those using screen readers or RSS readers. Google states that they use them for determining page relationships as well.
In a theme I am working on, I set several PHP session variables and cookies, some of which are specific to the current page the user is visiting.
While testing the theme, several of the session variables kept on getting set or reset during page load, in what seemed to be a nonsensical manner. Sometime between the time the page had fully loaded and refreshing the page, the session and cookie variables would change.
Generally, when a php session variable is reset, it is user error and I suppose that is sort of the case here. So, I spent a bit of time checking the state of the variable at various places and couldn’t figure out where it was getting reset or why. It, unfortunately, took a bit too long for me to remember the last time Firefox prefetching has bit me.
What was happening was that Firefox was prefetching the rel=’next’ element in the header at some point after the page was rendered, specifically ‘browser idle time.’ As a result, sometime after the current page was loaded, the ‘next’ page would be prefetched and session variables would be updated to that page, changing them from the expected results.
There is an interesting article on MDN that describes Link Prefetching in Firefox, both their reasons and responses to some of the more common concerns with the Mozilla approach. These is also a bug from 2011, which discusses it.
Essentially, the page is loaded in the background for several elements, including ‘prefetch’ and ‘next’ <link> elements, as well as meta tags that include ‘ rel=prefetch’ in the content section. They state that Firefox appends an ‘X-moz: prefetch’ header to these requests, so you can distinguish between a direct visit and a pre-fetch.
In addition, they have sections that cover some problems this causes, like increased bandwidth usage and privacy concerns(as cookies and session info is also accessed.)
They address the bandwidth issue as, essentially, a security concern that keeps people honest stating that:
It is important that websites adopt <link> tag based prefetching instead of trying to roll-in silent downloading using various JS/DOM hacks. The <link> tag gives the browser the ability to know what sites are up to, and we can use this information to better prioritize document prefetching. The user preference to disable <link> tag prefetching may simply encourage websites to stick with JS/DOM hacks, and that would not be good for users. This is one reason why prefetching is enabled by default.
Personally, this doesn’t strike me as a compelling reason to fetch resources within a ‘next’ element, although explicitly using a ‘prefetch’ element or meta tag is different. That makes sense, as a web developer being able to explicitly tell the browser to prefetch something is a neat feature. Where that doesn’t make sense, however, is to do it without being told to, as is the case when you include a prev and next link.
For one, most users probably don’t even know this is happening, so even though it can be disabled by users, most probably won’t know it is going on or why they would want to disable this. Those on limited bandwidth, both on the web server side and client side, are likely wasting a good bit of resources to these prefetches. In regards to webservers, not all users are going to visit the page in the first place, so you are wasting file or database reads. Further, this presents an easy and innocuous way of tracking firefox users or setting cookies, which would work even if you had scripts, iframes, and other security measures in place. Although, ultimately, this security risk is rather small, especially if you let the website run Javascript, as there are worse things that could be done.
While they state that this is within spec, pointing that WC3 permits the addition of new ‘link’ element types, using the next element in this manner is a bit of a stretch. I don’t think it is a great design choice. However, as stated above, having some sort of preftech mechanism does make sense and is cool to have built in.
I did some quick checking in Chrome, Internet Explorer 8 and Internet Explorer 10 and none seem to prefetch the ‘next’ element, or at least not in the same manner as Firefox. Also, the browser test page that is provided by Mozilla to determine if your browser supports prefetching fails in a current build of chrome.
I did not verify that resources were being loaded in these browsers, but none appear to be accessing cookies.
There are a few ways to address this, one would be to check for the ‘X-moz: prefetch’ header and respond accordingly.
Personally, I opted to simply remove the ‘prev’ and ‘next’ links from the WordPress header by adding the following to my functions.php:
remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 ); remove_action( 'wp_head', 'start_post_rel_link', 10, 0 ); remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
There are a few issues with this fix and it certainly reduces accessibility, both for users using screen readers, as well as for search engines that might use these as a cue to the relationship between pages. Adding a header check would arguably be a better way, although in the above bug report this seems to cause issues with certain proxies and can cause certain issues. Rethinking this particular php function and its use of Cookies is another option.
However, getting an extra +1 hit on each page Firefox visits likely adds unneeded database and filesystem calls, as most users aren’t using them. As such, reducing the impact of Firefox users on website and database calls provides a compelling reason to remove these links.
Add a Comment