I've been reading quite a bit of climate literature recently, and it got me thinking of what my impact is in the world. This will probably be a multiple part series, but as a starter for ten I wondered how climate friendly is this blog. And if it's not, how could it be improved.
To start with it's worth investigating the current state.
Current State
An evaluation on websitecarbon shows that we're pretty good, only 0.06g of carbon produced on a site visit, but we can probably do better.
Going through some of the suggestions there was some pretty quick wins in terms of increasing efficiency and reducing the footprint.
Reducing Image Size
Currently images are generated in a variety of different sizes to aid slower browsers. However they are slightly over-eager currently.
images: {
loader: 'custom',
imageSizes: [16, 64, 128, 256, 384],
deviceSizes: [320, 640, 1080, 1920, 2048],
},
images: {
loader: 'custom',
imageSizes: [16, 64, 128, 256, 384],
deviceSizes: [320, 640, 1080, 1920, 2048],
},
Cutting this back reduces the eventual generated images by nearly half. Big success.
images: {
loader: 'custom',
imageSizes: [16, 64, 128, 256],
deviceSizes: [320, 1080, 1920],
},
images: {
loader: 'custom',
imageSizes: [16, 64, 128, 256],
deviceSizes: [320, 1080, 1920],
},
Progressive Web Apps (PWA)
PWAs allow web applications to be directly installed onto a users device, offering the ability to work while a users device is offline. Alongside this they are also able to update content in the background, and display notifications utilising the OS notification system.
I'll probably have a separate article devoted to PWAs in the future, but for the moment the main point I'll be focussing on is the caching support. This reduces the number of calls being made for images, and improving the performance for the user.
A barebones PWAs implementation for Next is pretty simple using next-pwa
.
Updating from the existing:
const mdx = withMDX(mdxConfig);
module.exports = {
...mdx,
publicRuntimeConfig: {
version,
}
}
const mdx = withMDX(mdxConfig);
module.exports = {
...mdx,
publicRuntimeConfig: {
version,
}
}
to
// Merge MDX config with Next.js config
const mdx = withMDX(mdxConfig);
const withPWA = require('next-pwa')({
dest: 'public'
});
module.exports = {
...withPWA(mdx),
publicRuntimeConfig: {
version,
}
}
// Merge MDX config with Next.js config
const mdx = withMDX(mdxConfig);
const withPWA = require('next-pwa')({
dest: 'public'
});
module.exports = {
...withPWA(mdx),
publicRuntimeConfig: {
version,
}
}
Unbreaking Dev
Due to the way PWAs are constructed, a dev environment isn't really suited to cached requests and service workers, with this warning appearing consistently:
WARNING in InjectManifest has been called multiple times, perhaps due to running webpack in --watch mode
With some minor changes to next.config.js
I was able to ensure PWA support was disabled locally.
const prod = process.env.NODE_ENV === 'production';
const withPWA = require('next-pwa')({
dest: 'public',
disable: !prod,
});
const prod = process.env.NODE_ENV === 'production';
const withPWA = require('next-pwa')({
dest: 'public',
disable: !prod,
});
Making Efficient Crawlers
Web crawlers can be a bit of a drag on a website, so giving them instructions on the optimal way to crawl a website can help to reduce the number of requests being made.
The initial starting point was to stop crawlers operating on my quotes page. Who needs more inspiring one-liners thrown into the abyss?
User-agent: *
Disallow: /quotes
However, adding a sitemap (a file containing the relationship between a websites pages) alongside this seemed pretty useful, and doing this manually was going to be relatively painful each time a new post was added.
Time to turn to another library - next-sitemap.
This is a next integration which enables the generation of sitemaps and robots.txt as a build-step.
Setting it up was relatively simple:
Offline Fallback
Adding offline support with next-pwa
is relatively trivial, and aids in reducing the number of requests. All it takes is adding a page under
_fallback.tsx
. Pretty trivial currently but give it a spin if you feel like it.
const Fallback = () => (
<h1>This is an offline fallback page.</h1>
);
export default Fallback;
const Fallback = () => (
<h1>This is an offline fallback page.</h1>
);
export default Fallback;
Although admittedly this does little in terms of reducing requests to a webste, it's a pretty snazzy feature.
Conclusion
The carbon footprint of the site has been slighly reduced through these steps, although this was already shaving a pretty thin coat.
The image below gives an overview of the image heaviest page present on the site, with the main negative on the UX side coming from the number
of DOM elements generated by the remark
and rehype
plugins I have working on the formatted MDX.
I'll probably come back to this at a future date - potentially stripping out all the JS from this site - I'm just enjoying playing around too much currently.