My blog was built a long time ago using Gatsby. I vaguely remember cloning it from a template, but I can’t recall the exact name.
Over the years, I have added various features, such as the talks page, as I started giving talks.
The blog was initially built with Gatsby 1 and has been upgraded to Gatsby 2, where it has remained ever since. Although Gatsby 2’s support ended in 2021, I have procrastinated upgrading to the latest version, Gatsby 5. Since my blog is still functional and allows me to add new articles and talks, I haven’t felt a strong urge to perform a complete revamp or refactoring. It has become somewhat of a legacy system that continues to serve its purpose.
Here is the current package.json
:
"dependencies": {
"@sentry/gatsby": "^5.29.2",
+ "gatsby": "2.32.13",
"gatsby-plugin-canonical-urls": "2.9.0",
"gatsby-plugin-catch-links": "^2.0.4",
"gatsby-plugin-feed": "^2.0.8",
"gatsby-plugin-google-analytics": "^2.0.6",
"gatsby-plugin-google-fonts": "latest",
"gatsby-plugin-next-seo": "^1.6.1",
"gatsby-plugin-offline": "^2.0.6",
"gatsby-plugin-react-helmet": "^3.0.0",
"gatsby-plugin-sass": "^2.0.1",
"gatsby-plugin-sharp": "^3.15.0",
"gatsby-plugin-sitemap": "^2.0.1",
"gatsby-remark-autolink-headers": "^2.1.17",
"gatsby-remark-copy-linked-files": "^2.0.5",
+ "gatsby-remark-images": "^6.12.1",
"gatsby-remark-prismjs": "^3.0.2",
Perhaps one day, I will migrate the blog to Astro, but that remains a future endeavor. As a first step, I plan to migrate all my markdown files to a Notion database and connect my blog to fetch content from Notion instead of using the current markdown files. This change alone would be quite helpful. So, what’s the issue at hand?
In a recent article, I highlighted the awesomeness of the loading='lazy'
property for images. I want to ensure that my blog also benefits from this feature. I recall adding the loading: 'lazy'
option to gatsby-remark-images
, which should apply the loading='lazy'
attribute to all images by default.
{
resolve: 'gatsby-transformer-remark',
options: {
tableOfContents: {
maxDepth: 4,
},
plugins: [
'gatsby-remark-autolink-headers',
'gatsby-remark-lazy-gif',
{
resolve: 'gatsby-remark-images',
options: {
maxWidth: 960,
+ loading: 'lazy',
linkImagesToOriginal: true,
},
However, upon reviewing my latest article, I noticed that the GIF files do not have the loading='lazy'
property. Consequently, when visiting the page, the GIF files load immediately, resulting in a significant amount of data being loaded, especially for larger GIF files. Since many of my blog posts include GIF files to showcase visual content, this issue needs to be addressed. For example, the Angular v17’s View Transitions: Navigate in Elegance contains several GIF files and at the moment, when you enter the page, all 12 GIF files are loaded immediately, costing about 70mb
of data.
While I have configured gatsby-remark-images
to include the loading='lazy'
property by default for most images, GIF files are not processed by this plugin. For example, the following JPG file has the loading='lazy'
property:
But the GIF file does not have the loading='lazy'
property. The img tag below only has the src
and alt
attributes:
<img src="/0a94a1f59b4ffa9c061154716bd42de2/angular-view-transitions-07.gif" alt="Customised Transition">
The reason why GIFs are excluded can be found in the gatsby-remark-images
documentation and some related issues:
What I want is simple: adding the loading='lazy'
property to GIF files. Since gatsby-remark-images
doesn’t support GIFs, I need to find an alternative solution.
- <img src="/0a94a1f59b4ffa9c061154716bd42de2/angular-view-transitions-07.gif" alt="Customised Transition">
+ <img src="/0a94a1f59b4ffa9c061154716bd42de2/angular-view-transitions-07.gif" alt="Customised Transition" loading="lazy">
Searching Google doesn’t yield any straightforward solutions.
Thus, I decided to ask ChatGPT for help. Here is the conversation:
See the full conversation here.
gatsby-config.js
for gatsby-remark-images
Basically, ChatGPT suggested updating the gatsby-config.js
that utilise wrapperStyle
from gatsby-remark-images
. This custom transformer will add the loading="lazy"
attribute to .gif images.
// gatsby-config.js
module.exports = {
siteMetadata: {
// Your site metadata
},
plugins: [
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
{
resolve: 'gatsby-remark-images',
options: {
maxWidth: 800,
loading: 'lazy', // Default loading for images
+ wrapperStyle: (fluidResult) =>
+ fluidResult.src.endsWith('.gif') ? 'loading="lazy"' : '',
+ },
},
],
},
},
// Other plugins
],
}
However, as gatsby-remark-images
doesn’t support GIFs, this approach won’t work because the wrapperStyle
function is only applied to images processed by gatsby-remark-images
. GIFs are not processed by this plugin.
So I asked for a follow-up, and ChatGPT suggested writing a custom plugin
to handle GIFs.
Below are the steps suggested by ChatGPT:
If gatsby-remark-images
is filtering out .gif images and you need to add loading="lazy"
to them, you can use a custom plugin to directly modify the markdown AST before gatsby-remark-images
processes it. Here’s how you can achieve this:
mkdir -p plugins/gatsby-remark-lazy-gif
gatsby-remark-lazy-gif
, create an index.js
file with the following content:// plugins/gatsby-remark-lazy-gif/index.js
const visit = require('unist-util-visit');
module.exports = ({ markdownAST }) => {
visit(markdownAST, 'image', node => {
if (node.url.endsWith('.gif')) {
node.data = node.data || {};
node.data.hProperties = node.data.hProperties || {};
node.data.hProperties.loading = 'lazy';
}
});
return markdownAST;
};
gatsby-config.js
to use the custom plugin before gatsby-remark-images
:// gatsby-config.js
module.exports = {
siteMetadata: {
// Your site metadata
},
plugins: [
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
+ 'gatsby-remark-lazy-gif', // Add the custom plugin here
{
resolve: 'gatsby-remark-images',
options: {
maxWidth: 800,
},
},
I followed the instructions and created the custom plugin. Then, I updated the gatsby-config.js
to include the custom plugin before gatsby-remark-images
. However, it threw an error:
Plugin gatsby-remark-lazy-gif requires a package.json file
I asked for further guidance, and ChatGPT suggested creating a package.json
file for the plugin, as seen in the conversation below:
And voila! It works! Now all my GIF files have the loading='lazy'
property. As you scroll down the page, the GIF files are loaded dynamically, reducing the initial data load.
To boost website performance, add loading='lazy'
to the img
tag. While Gatsby’s default image transformer, gatsby-remark-images
, doesn’t support GIFs, we can create a custom plugin to handle them.
ChatGPT has been super helpful in creating the plugin and solving this problem. I am a daily use of AI tools such as Copilot, ChatGPT and others and I really appreciate the value they bring to my work. This article was also written with ChatGPT’s help for grammar and suggestions.