DEV Community

Cover image for How I made WordPress Faster with 1KB JavaScript
Gijo Varghese
Gijo Varghese

Posted on • Updated on

How I made WordPress Faster with 1KB JavaScript

Clickbait title right? 😉

Released 4 months ago, the script is currently used by 4k WordPress sites.

GitHub logo gijo-varghese / flying-pages

Load inner pages instantly, intelligently

Flying Pages

Flying Pages prefetch pages before the user click on links, making them load instantly

Quick Links

Buy Me A Coffee

Usage

Quickstart:

<script src="flying-pages.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

With options:

<script>
  window.FPConfig = {
    delay: 0,
    ignoreKeywords: [],
    maxRPS: 3,
    hoverDelay: 50,
  };
</script>
<script defer src="flying-pages.min.js"></script>
Enter fullscreen mode Exit fullscreen mode
  • delay: Start prefetching after a delay (in seconds). Will be started when the browser becomes idle, using requestIdleCallback. Default to 0.
  • ignoreKeywords: An array of keywords to ignore from prefetching. Example ['/logout','/cart','about.html','sample.png','#'].
  • maxRPS: Maximum requests per second the queue should process. Set to 0…
<script src="flying-pages.min.js"></script>
<script>
  flyingPages({
      delay: 0,
      ignoreKeywords: [],
      maxRPS: 3,
      hoverDelay: 50
  });
</script>
Enter fullscreen mode Exit fullscreen mode

How it works?

Flying Pages injects a tiny JavaScript code (1KB gzipped) that waits until the browser becomes idle, detect links in the viewport (also on mouse hover) and prefetch them so that browser doesn't have to wait while navigating through pages.

The prefetching is done using the prefetch tag:

<link rel="prefetch" href="URL_TO_PAGE">
Enter fullscreen mode Exit fullscreen mode
  • Prefetch pages in the viewport – Detect links within the viewport (current viewing area) using ‘Intersection Observer’ and tells the browser to prefetch them using ‘prefetch’

  • Prefetch pages on mouse hover – On hovering links, if it’s not prefetched yet using above ‘viewport’, then Flying Pages will prefetch them instantly (similar to Instant.page).

  • Limits the number of prefetches per second – If your page has too many links, prefetching all at the same time will cause the server to crash or slow down the website to visitors. Flying Pages limits the number of prefetches per second (3 req/sec by default) using an in-built queue.

  • Stops prefetching if the server is busy – In case the server starts to respond slowly or return errors, prefetching will be stopped to reduce the server load.

  • Understands user’s connection and preferences – Checks if the user is on a slow connection like 2G or has enabled data-saver. Flying Pages won’t prefetch anything in this case.

Demo

WordPress Plugin

Prefetching links to logout, cart page etc can cause issues. So we need to exclude such links as well as few other options like:

  • Set maximum requests per second
  • Delay to start prefetching
  • Mouse hover delay
  • Disable for logged in admins

The Flying Pages WordPress plugin comes with a settings panel to configure all these:

WordPress Plugin Settins

Demo?

Check out my blog WP Speed Matters

Top comments (30)

Collapse
 
kimschulz profile image
Kim Schulz

I tested it with my installation but it is useless if you have WordPress+woocommerce. It removed items from the cart when the customer entered the cart listing.... It simply trigger the links to remove items from there. It also generates a lot of irrelevant traffic to the server.

Collapse
 
gijovarghese profile image
Gijo Varghese

You've to exclude those links. It usually depends on the theme, that's why I couldn't add it to the default ignore list

Collapse
 
pavelloz profile image
Paweł Kowalski
Collapse
 
gijovarghese profile image
Gijo Varghese

Instant.page is different from Flying Pages. Read Instant.page vs Flying Pages

Collapse
 
znuff profile image
Bogdan I.

I'd address the 300ms+ ttfb first...

Thread Thread
 
gijovarghese profile image
Gijo Varghese

SSL handshake from server to a location halfway around the globe itself takes 250+ms.

Thread Thread
 
brettsschmidt profile image
Brett Schmidt

You could just use a CDN.

Thread Thread
 
gijovarghese profile image
Gijo Varghese

CDN only fixes latency for static files. This is for dynamically generated HTML pages

Thread Thread
 
pavelloz profile image
PaweÅ‚ Kowalski • Edited

For those looking for issues and needing wordpress plugins to slap some js on their pages, here ya go, copy paste to your page (layout) and you are golden.

/*! instant.page v3.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license */
let t,e;const n=new Set,o=document.createElement("link"),s=o.relList&&o.relList.supports&&o.relList.supports("prefetch")&&window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype,i="instantAllowQueryString"in document.body.dataset,r="instantAllowExternalLinks"in document.body.dataset,a="instantWhitelist"in document.body.dataset;let c=65,d=!1,l=!1,u=!1;if("instantIntensity"in document.body.dataset){const t=document.body.dataset.instantIntensity;if("mousedown"==t.substr(0,"mousedown".length))d=!0,"mousedown-only"==t&&(l=!0);else if("viewport"==t.substr(0,"viewport".length))navigator.connection&&(navigator.connection.saveData||navigator.connection.effectiveType.includes("2g"))||("viewport"==t?document.documentElement.clientWidth*document.documentElement.clientHeight<45e4&&(u=!0):"viewport-all"==t&&(u=!0));else{const e=parseInt(t);isNaN(e)||(c=e)}}if(s){const n={capture:!0,passive:!0};if(l||document.addEventListener("touchstart",function(t){e=performance.now();const n=t.target.closest("a");if(!f(n))return;h(n.href)},n),d?document.addEventListener("mousedown",function(t){const e=t.target.closest("a");if(!f(e))return;h(e.href)},n):document.addEventListener("mouseover",function(n){if(performance.now()-e<1100)return;const o=n.target.closest("a");if(!f(o))return;o.addEventListener("mouseout",m,{passive:!0}),t=setTimeout(()=>{h(o.href),t=void 0},c)},n),u){let t;(t=window.requestIdleCallback?t=>{requestIdleCallback(t,{timeout:1500})}:t=>{t()})(()=>{const t=new IntersectionObserver(e=>{e.forEach(e=>{if(e.isIntersecting){const n=e.target;t.unobserve(n),h(n.href)}})});document.querySelectorAll("a").forEach(e=>{f(e)&&t.observe(e)})})}}function m(e){e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||t&&(clearTimeout(t),t=void 0)}function f(t){if(t&&t.href&&(!a||"instant"in t.dataset)&&(r||t.origin==location.origin||"instant"in t.dataset)&&["http:","https:"].includes(t.protocol)&&("http:"!=t.protocol||"https:"!=location.protocol)&&(i||!t.search||"instant"in t.dataset)&&!(t.hash&&t.pathname+t.search==location.pathname+location.search||"noInstant"in t.dataset))return!0}function h(t){if(n.has(t))return;const e=document.createElement("link");e.rel="prefetch",e.href=t,document.head.appendChild(e),n.add(t)}
Thread Thread
 
gijovarghese profile image
Gijo Varghese

This will preload all the links which will cause many issues like logging out users, adding unwanted products to cart, removing items from cart etc.

Also Instant.Page will preload all the links which can crash servers

Thread Thread
 
pavelloz profile image
PaweÅ‚ Kowalski • Edited

Do you have any proof/example of precaching crashing any server?

And how is this not applying to the wp thingie?

Thread Thread
 
gijovarghese profile image
Gijo Varghese

I think you haven't read the blog post I linked before wpspeedmatters.com/quicklink-vs-in...

Collapse
 
shaijut profile image
Shaiju T • Edited

Interesting plugin,Thanks :) Some points and question:

  1. In this post you are saying preload and using prefetch tag , its confusing for reader because preload and prefetch are different concepts.

  2. I tested your demo website home page:

  • In home page after load, I took a full screenshot , its here, As you can see initially all images are blank , as we scroll it loads the image, so does this plugin just lazy loads images ?

  • I click on a article, I expected whole article to be cached using prefetch in browser, but in network tab i can see it is pulling the html from server instead.

Can you create separate demo website for the plugin with little assets and articles and explain step by step why this plugin is useful.

Collapse
 
gijovarghese profile image
Gijo Varghese
  1. Thanks for pointing this out. Corrected!

2.1 - The images are lazy loading using my other plugin, Flying Images. Flying Pages doesn't lazy load images.

2.2 - On clicking prefetched article, it will still show in the network tab, but the 'size' would be 'prefetch cache'. Make sure "Disable Cache" is unchecked. Here is how you can check if it's working properly or not: youtube.com/watch?v=T658UlOKdx8

Collapse
 
alexmacarthur profile image
Alex MacArthur

I love that this solution specifically addresses challenges other options struggle with (QuickLink, Instant.page, etc.).

It's worth calling out, though, that preloading is not the same as prefetching. A true preload would fully render the page in a background tab, and can only handle one page at a time. Prefetching simply fetches the document, but doesn't parse any of its contents, including any CSS or JS called by that fetched page. Therefore, it's much less resource-intensive than preloading. They both serve important performance-related purposes, but are still very different. I wrote about this in more depth here:

macarthur.me/posts/best-ish-practi...

Collapse
 
gijovarghese profile image
Gijo Varghese • Edited

Yes, Flying Pages use prefetch. The prerender will consume too much bandwidth and cause issues in reporting tools like Google Analytics

Collapse
 
nicolaerario profile image
Nicola Erario

There are some special settings or precaution for woocommerce? like disable /checkout in addition to /cart page

Collapse
 
gijovarghese profile image
Gijo Varghese

Adding "checkout" and "cart" to the ignore list should fix most of the issues. It's also good to add "?" to the list so that any links that update quantity or something via query parameters will not be preloaded

Collapse
 
gijovarghese profile image
Gijo Varghese • Edited

Flying Pages doesn't decrease the load time of the page. It only speeds up inner page navigation. That is when you open the site and click on any link

 
gijovarghese profile image
Gijo Varghese

If you open the network tools and open a link, you'll see size as "preload cache". Test it out in an incognito window if you've disabled it for admins

Collapse
 
jsardev profile image
Jakub Sarnowski

Wow, didn't know about this tool! Thanks!

Collapse
 
gijovarghese profile image
Gijo Varghese

Welcome :)

Collapse
 
wplogout profile image
WP Logout • Edited

Thanks for the plugin. I have implemented it on my website. wplogout.com
It is working like a charm. Thanks, Gijo.

Collapse
 
blogging_idol profile image
BloggingIdol

Great plugin thinking to implement it on my blog bloggingidol.com.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.