To make my site load a bit quicker, I have decided to add more advanced image handling. This will be in two parts: using Imgix to render the images in the best way possible and the other being a media handling plugin that will return an image that is automatically formatted (from imgix based on the users' device) and in an appropriate size. A small addition to this that has already been implemented is "loading=lazy" on all images which will make the images lazy load on supported browsers (everything except for IE11).
Imgix:
I have used Imgix previously so implementing it won't be that much of an issue. I will mainly use the auto=format feature to make the returning image be the best format possible for the user and also setting the height and width to what the actual shown size should be.
Media handler:
This will be a plugin in nuxt that will have a method for inputting an image, a size/ratio, and then returning the most perfect image ever.
Since I am using nuxt-ts and composition API the code for the plugin is as follows:
import { Plugin } from '@nuxt/types'; declare module '@nuxt/types' { interface NuxtAppOptions { $toMediaUrl(slug: string, args: MediaArguments): string } interface Context { $toMediaUrl(slug: string, args: MediaArguments): string } } interface MediaArguments { maxHeight: number; maxWidth: number; skipAutoFormat?: boolean | undefined; } function toMediaUrl(slug: string, { maxHeight, maxWidth, skipAutoFormat = false }: MediaArguments) { const qs = []; if (maxWidth) { qs.push(`maxWidth=${Math.round(maxWidth)}`); } if (maxHeight) { qs.push(`maxHeight=${Math.round(maxHeight)}`); } if (!skipAutoFormat) { qs.push('auto=format'); } let imageUrl = `https://sebbejohansson.imgix.net/${slug}`; if (qs.length) { imageUrl += `?${qs.join('&')}`; } return imageUrl; } const mediaHandler: Plugin = (context, inject) => { context.$toMediaUrl = toMediaUrl; inject('toMediaUrl', toMediaUrl); }; export default mediaHandler;
import { Plugin } from '@nuxt/types';
declare module '@nuxt/types' {
interface NuxtAppOptions {
$toMediaUrl(slug: string, args: MediaArguments): string
}
interface Context {
$toMediaUrl(slug: string, args: MediaArguments): string
}
}
interface MediaArguments {
maxHeight: number;
maxWidth: number;
skipAutoFormat?: boolean | undefined;
}
function toMediaUrl(slug: string, { maxHeight, maxWidth, skipAutoFormat = false }: MediaArguments) {
const qs = [];
if (maxWidth) {
qs.push(`maxWidth=${Math.round(maxWidth)}`);
}
if (maxHeight) {
qs.push(`maxHeight=${Math.round(maxHeight)}`);
}
if (!skipAutoFormat) {
qs.push('auto=format');
}
let imageUrl = `https://sebbejohansson.imgix.net/${slug}`;
if (qs.length) {
imageUrl += `?${qs.join('&')}`;
}
return imageUrl;
}
const mediaHandler: Plugin = (context, inject) => {
context.$toMediaUrl = toMediaUrl;
inject('toMediaUrl', toMediaUrl);
};
export default mediaHandler;