Improve web performance lazy loading reCaptcha
Last updated
Antonio Ufano
A few days ago I ran Lighthouse in a couple of my websites and the performance score wasn't very good (around ~50). Most of the recommendations provided to improve the score were server side, like caching and compressing assets but the score gains when I applied them was not that good. I realized that what was impacting the website performance the most was reCaptcha.
I use reCaptcha in every page that contains a form to avoid spam so getting rid of it was not an option. After searching online for some ways to improve the situation, I found this article which explained how to solve all my issues. The solution is awesome by its simplicity: do not load recaptcha on the initial page load but lazy load it when the user actually interacts with one of your forms .
Let's say we have a page with a simple subscription form and we load reCaptcha as it's detailed in their docs:
<html>
<head>
<title>My page</title>
</head>
<body>
<header>
<h1>My awesome website</h1>
</header>
<main>
<form id="contactForm" action="#" method="POST">
<input
aria-label="Name"
id="sub_name"
type="text"
required
placeholder="Johnny Mnemonic"
/>
<input
aria-label="Email address"
id="subEmail"
type="email"
required
placeholder="eightgigs@memory.com"
/>
<input
id="submitBtn"
value="Subscribe"
type="submit"
data-sitekey="GOOGLE_RECAPTCHA_KEY"
data-callback="sendForm"
/>
</form>
</main>
<!-- reCaptcha API JS -->
<script src="https://www.google.com/recaptcha/api.js" defer></script>
<script>
function sendForm() {
document.getElementById('contactForm').submit()
}
</script>
</body>
</html>
The reCaptcha API library is loaded with the page, just 1.2KB, but it automatically triggers a request to https://www.gstatic.com/recaptcha/releases/ which adds another extra 127KB to our page. And what happens if the user never interacts with the form? We've loaded a JavaScript file for no reason at all.
The solution is pretty simple and easy to implement:
<html>
<head>
<title>My page</title>
</head>
<body>
<header>
<h1>My awesome website</h1>
</header>
<main>
<form id="contactForm" action="#" method="POST">
<input
aria-label="Name"
id="subName"
type="text"
required
placeholder="Johnny Mnemonic"
/>
<input
aria-label="Email address"
id="subEmail"
type="email"
required
placeholder="eightgigs@memory.com"
/>
<input
id="submitBtn"
value="Subscribe"
type="submit"
data-sitekey="GOOGLE_RECAPTCHA_KEY"
data-callback="sendForm"
/>
</form>
</main>
<script>
function sendForm() {
document.getElementById('contactForm').submit()
}
// Function that loads recaptcha on form input focus
function reCaptchaOnFocus() {
var head = document.getElementsByTagName('head')[0]
var script = document.createElement('script')
script.type = 'text/javascript'
script.src = 'https://www.google.com/recaptcha/api.js'
head.appendChild(script)
// remove focus to avoid js error:
document
.getElementById('subName')
.removeEventListener('focus', reCaptchaOnFocus)
document
.getElementById('subEmail')
.removeEventListener('focus', reCaptchaOnFocus)
}
// add initial event listener to the form inputs
document
.getElementById('subName')
.addEventListener('focus', reCaptchaOnFocus, false)
document
.getElementById('subEmail')
.addEventListener('focus', reCaptchaOnFocus, false)
</script>
</body>
</html>
Let me explain what's happenning here:
- We're no longer loading the reCaptcha API JS library by default
- We've declared a function recaptchaOnFocus that adds the script tag with the reCaptcha API JS library to our page header when it's invoked.
- We've added event listeners in our form inputs to invoke the recaptchaOnFocus function.
This way, our initial page load has 2 less requests and we've saved 128KB. For me that was the difference between these two results:
I hope this helps you improve your page load times but don't apply this just to reCaptcha. Think about other libraries you might be loading by default in your pages that can be lazy loaded in a similar way. I'm sure you'll be able to find some of them that are only necessary in edge cases.
Happy coding!
If you enjoyed this article consider sharing it on social media or buying me a coffee ✌️
Oh! and don't forget to follow me on Twitter where I share tons of dev tips 🤙
Other articles that might help you
my projects
Apart from writing articles in this blog, I spent most of my time working on my personal projects.
theLIFEBOARD.app
theLIFEBOARD is a weekly planner that helps people achieve their goals, create new habits and avoid burnout. It encourages you to plan and review each week so you can easily identify ways to improve your productivity while keeping track of your progress.
Sign upSolidityTips.com
I'm very interested in blockchain, smart contracts and all the possiblilities chains like Ethereum can bring to the web. SolidityTips is a blog in which I share everything I learn about Solidity and Web3 development.
Check it out if you want to learn SolidityQuicktalks.io
Quicktalks is a place where indie hackers, makers, creators and entrepreneurs share their knowledge, ideas, lessons learned, failures and tactics they use to build successfull online products and businesses. It'll contain recorded short interviews with indie makers.
Message me to be part of it