Take control over your media loading

Rmag Breaking News

MediaLoader is a versatile React component that provides fine-grained control over the loading of media assets such as images, videos, and audio files. It offers a customizable loading strategy, allowing developers to prioritize resources and optimize user experience.

It has been a while, I know.
Hopefully I have something for you that will compensate for my absence 🙂

As you may already know, web performance has become increasingly significant within the frontend community. Those who value their work and prioritize user experience dedicate considerable effort to enhancing the performance of their websites and applications.

Improving performance involves loading only essential resources, allowing the network connection to prioritize critical assets and expedite the page’s readiness and interactivity.
Media content—such as images, videos, and audio—typically constitutes the bulk of data to be loaded. Moreover, when the browser encounters a media tag during document parsing, it initiates immediate loading by default.

The “lazy” attribute for the img tag aims to alleviate network load by enabling the deferred loading of images until necessary. When you use the lazy attribute, the browser will only load the image when it enters the viewport, helping to conserve bandwidth and improve page loading times, especially on pages with many images.

However, this is insufficient. We recognize that viewport entry alone may not always suffice as the desired trigger. There are instances where we might prefer loading based on observing a CSS property or clicking an element, among other examples. Additionally, it’s important to note that images are not the sole type of media content we aim to lazy-load, yet they unfortunately lack support for such functionality.

This is where the MediaLoader comes in to fill the gap.

MediaLoader is a versatile React component that provides fine-grained control over the loading of media assets such as images, videos, and audio files. It offers a customizable loading strategy, allowing developers to prioritize resources and optimize user experience.

With MediaLoader, you can effortlessly manage the loading process, dynamically loading media content based on user interactions, viewport visibility and much more. Whether you’re building a gallery, a multimedia-rich website, or an application with heavy media content, MediaLoader empowers you to deliver a seamless and performant user experience.

MediaLoader is designed to be as non-intrusive as possible, integrating into your existing React applications without imposing a heavy footprint and without changing the DOM structure. It provides a lightweight wrapper around your current media, without requiring a complete overhaul of your codebase.

You can check out some demo examples in this Storybook, and see the code in the pedalboard repo.

How do I use it?

You first need to install it:

yarn add @pedalboard/media-loader

Or

npm install @pedalboard/media-loader

Now, say you have this JSX:

<img src=/assets/image-04.jpg alt=image-04></img>
<img src=/assets/image-05.jpg alt=image-05></img>
<img src=/assets/image-06.jpg alt=image-06></img>
<div>
<img src=/assets/image-09.jpg alt=image-09></img>
</div>

All you need to do is to wrap it with the MediaLoader component and provide a loading strategy to it, like so:

import MediaLoader from @pedalboard/media-loader;

<MediaLoader
loadingStrategy={(mediaHTMLElementRefs, loadMedia) => {
// You loading strategy here
}}
>
<img src=/assets/image-04.jpg alt=image-04></img>
<img src=/assets/image-05.jpg alt=image-05></img>
<img src=/assets/image-06.jpg alt=image-06></img>
<div>
<img src=/assets/image-09.jpg alt=image-09></img>
</div>
</MediaLoader>

The loadingStrategy is a function which receives 2 arguments – An array of the media element refs and the loadMedia function. When you call the loadMedia function with a given ref it will load the associated media for it, whether it is an image, video or audio.

Your loading strategy might be something like this:

loadingStrategy={(mediaHTMLElementRefs, loadMedia) => {
const intersectionCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let elem = entry.target;
loadMedia(elem);
}
});
};
let options = {
rootMargin: 0px,
threshold: 1.0,
};
let observer = new IntersectionObserver(intersectionCallback, options);

mediaHTMLElementRefs.forEach((mediaHTMLElementRef) => {
let target = mediaHTMLElementRef.current;
if (target) {
observer.observe(target);
}
});
}}

In the example above we act the same as the lazy attribute of an img tag. Once the element intersects the viewport, we trigger the load.

You can now probably see the great control it allows you to have over your media content loading. Another example can be monitoring the left CSS property of the element and only when it surpasses 300, load it’s media content:

import MediaLoader from @pedalboard/media-loader;

<MediaLoader
loadingStrategy={(mediaHTMLElementRefs, loadMedia) => {
const monitor = (target) => {
const computedStyle = getComputedStyle(target.parentElement);
const currentLeft = parseFloat(computedStyle.left);
// If the image container reach a certain left then load it
if (currentLeft > 300) {
loadMedia(target);
return;
}

// Continue monitoring in the next frame
requestAnimationFrame(() => monitor(target));
};

mediaHTMLElementRefs.forEach((mediaHTMLElementRef) => {
let target = mediaHTMLElementRef.current;
if (target) {
requestAnimationFrame(() => monitor(target));
}
});
}}
>
<div
className=image-container
onClick={(event) => {
(event.target as HTMLDivElement).classList.add(animate-media);
}}
>
<img src=/assets/image-01.jpg alt=image-09 className=run></img>
<div>And now me</div>
</div>
<div
className=image-container
onClick={(event) => {
(event.target as HTMLDivElement).classList.add(animate-media);
}}
>
<img src=/assets/image-02.jpg alt=image-09 className=run></img>
<div>Quick! Click me 😉</div>
</div>
<div
className=image-container
onClick={(event) => {
(event.target as HTMLDivElement).classList.add(animate-media);
}}
>
<img src=/assets/image-03.jpg alt=image-09 className=run></img>
<div>Click me 😉</div>
</div>
</MediaLoader>

You can read more about it in the project README file, download it from the NPM registry and start playing with it 🙂

I’d love to hear your thoughts and feedback on this project, and if it helped you produce a better performing web content.

Until next time,
Cheers!

Photo by USGS on Unsplash

Leave a Reply

Your email address will not be published. Required fields are marked *