How can you stop data URI from being cached as an image source?

I am facing an issue where I have an img-tag with a data-image base64 URI as the source. Browsers tend to cache this source, which is causing problems for me. If it were a normal URL, I could easily prevent caching by adding a random query-parameter value.

How can I prevent the caching of this data-image base64 URI source?

Here's an example of an img tag with a data-image base64 URI:

<img src="data:image/svg+xml;base64,PD94bWw==">

And here's an example of an img tag with a normal URL source along with a query param to avoid caching:

<img src="https://foo?1234RandomString">

In my case, since the original image is SVG, I could use a data-image SVG URI and add a custom attribute to the SVG to prevent caching, which works. I could also deploy the SVG as a file and use a URL with a query param, but I find both solutions quite unsightly.

PS: Why do I need it? I have a long list of img-tags and I want to implement lazy loading to generate the actual source URL lazily in vue3.

Consider this code snippet. Initially, the src is set to the data-image URI. When the image is lazily loaded, the actual source is created and set.

Issue: Lazy loading fails in Chrome if the initialSrc is cached for the first image, preventing the mechanism from working for subsequent images.

<img :src="mySource" loading="lazy" @load="onLoad">

const initialSrc = "data:image/svg+xml;base64,PD94bWw=="

const imageSrc = ref()
const onLoad = async () => {
      if (!imageSrc.value) {
        imageSrc.value = await createRealSrc();
      }
    };

const mySource = computed(() => imageSrc.value ?? initialSrc)

There are some doubts in comments that data URIs are actually loaded via a request. edit: Trigger warning. More nuanced than it seems. Take a look further down and in the comments. They are:

Screenshot of network tab that shows a GET request to a data URI

Some more clarifications:

Let's say you have two img-tags in your document:

<img src="http://image.png" loading="lazy">
<img src="http://image.png" loading="lazy">

In this scenario, the first img-tag will be loaded lazily, while the second will be immediately loaded after the first one because its src can be fetched from cache.

<img src="http://image.png" loading="lazy">
<img src="http://image.png?abc" loading="lazy">

In this scenario, both images will be loaded lazily as the URLs are different and cannot be taken from cache.

<img src="data:image/svg+xml;base64,PD94bWw==" loading="lazy">
<img src="data:image/svg+xml;base64,PD94bWw==" loading="lazy">

Here, the first img-tag will be loaded lazily, but the second will not be loaded lazily as it will be promptly loaded once the first one is loaded due to cache retrieval.

<img src="data:image/svg+xml;base64,PD94bWw==" loading="lazy">
<img src="data:image/svg+xml;base64,sdfsdfs==" loading="lazy">

In this last scenario, both images will load lazily since the URIs are unique and cannot be retrieved from cache.

Why does the img-tag load immediately instead of lazily when the image can be fetched from cache? The behavior I observe in Chrome leads me to believe that it may be an implementation detail or part of the current Chrome specification. It makes sense though - why trigger a lazy load when the data is already available in cache. However, I still require lazy-loading for my purpose as I intend to utilize it for performing expensive operations lazily.

Does using a data URI as a source really result in a GET request being made? According to the Chrome network tab, yes. Is it considered a real HTTP transaction? That remains uncertain. Edit: To clarify, there is no backend involved, so there is no TCP communication happening. Thus, it might not strictly adhere to real HTTP standards. However, internally Chrome treats it like a GET-request, recording a request/response in accordance with HTTP protocols. Real HTTP or not? Likely not purely authentic.

Is the data URI stored in cache? As per the Chrome network tab, it appears to be cached. My understanding suggests that image data gets stored in cache regardless of whether it originates from a file or a data URI.

Is the source loaded along with the image (and not beforehand) even when using a data URI? In my experience, I would affirmatively say yes. While I suspect it's part of the HTML spec, I lack concrete evidence to support this claim.

Answer №1

So much confusion has arisen, and I deeply regret that. Here are some innovative solutions that have been shared and that I believe deserve special attention:

Opt for a "plain" SVG-based data URI rather than a base64-encoded data URI.

By using a "plain" data URI, you can include a custom attribute with a random value to create a unique URI for the same image:

data:image/svg+xml,%3C%3Fxml version='1.0' **custom-attribute="random value"** encoding='UTF-8'%3F%3E%3Csvg width='282.21' height='48'...

If you are utilizing an SVG-based base64-encoded data URI, consider adding a base64-encoded comment.

Convert "<!-- random value -->" to base64 and append it to the base64-encoded data URI to make the URI distinct without altering the actual image. This method can also be used in place of the custom attribute mentioned earlier.

Incorporate a normal unique URL as the image source to streamline lazy loading processes.

This approach is particularly effective when dealing with lazy backend calls. Rather than lazily loading a data URI and subsequently executing a backend call onLoad, opt for a unique backend URL as the initial image source and initiate the backend call directly once the image source has been loaded lazily.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Formatting decimals with dots in Angular using the decimal pipe

When using the Angular(4) decimal pipe, I noticed that dots are shown with numbers that have more than 4 digits. However, when the number has exactly 4 digits, the dot is not displayed. For example: <td>USD {{amount| number: '1.2-2'}} < ...

How can I implement callback functions in joi validation?

Exploring the World of Coding I came across a code snippet online that caught my attention, but upon closer inspection, I realized it used Hapi/Joi which is now considered outdated. My question is how can I modify this code to work with Joi? app.post(&apo ...

Tips for building a responsive dropdown menu using data from a database query

Currently, I am fetching a list of companies from Firestore and attempting to display them as options in a dropdown menu. While the companies state is being populated correctly from Firestore, the options are not being created or updated dynamically. How c ...

Showcasing top performers via JavaScript tabs

I have two tabs on my webpage: "Overall Leaderboard" and "Weekly Leaderboard". Each tab displays a leaderboard with different scores. When I click on the "Overall Leaderboard" tab, it shows a leaderboard with specific scores. Now, my question is how can ...

Does vee validate only apply to the initial field?

I've gone ahead and created two modals, one for logging in (loginModal) and another for registering (registerModal). Users have the ability to seamlessly switch between the two. However, I've encountered an issue with the "VeeValidate" plugin. I ...

What is the best way to transfer an object between views in Django?

Background/Issue In my web application, I have a job that involves running a python script to log into LinkedIn. This script launches headless chromium, navigates to the LinkedIn login page, and logs in with the proper credentials. However, sometimes Link ...

Discover the following item using jQuery

Here is some HTML code that I have: <div class="form-group"> <input type="text" class="sequence valid"> </div> <div class="form-group"> <input type="text" class="sequence valid"> </div> <div class="som ...

Using makeStyles() in MUI for conditional rendering

Trying to dynamically change the value of backgroundColor under the property "& + $track" using props.disabled but it seems that MUI does not recognize it. Why could that be? const useStyles = makeStyles((theme) => ({ root: { overflow: "vis ...

Can you explain the distinction between employing express.urlencoded() with extended set to true as opposed to setting it to false along with performing manual JSON stringify/parse calls?

Within my NodeJS/Express server, I am faced with the decision of setting extended to either true or false for the urlencoded middleware: app.use(express.urlencoded({ extended: true/false })); I have come to understand that when set to false, it signifies ...

The comparison between exposing and creating objects in a Nodejs router file

Recently, I began using expressjs 4.0.0 and was impressed by the express.Router() object. However, a dilemma arose when I moved all my routes to another file - how do I expose an object to the routes file? In my server.js file: ... var passport = ...

Why does the custom method only trigger once with the addEventListener?

I am attempting to connect the "oninput" event of an input range element to a custom method defined in a corresponding typescript file. Here is the HTML element: <input type="range" id='motivation-grade' value="3" min="1" max="5"> This i ...

Sharing properties across various components with Next.js

I'm still getting the hang of using Next.js and encountering issues with sharing data between components. Currently, I have a setup involving three components: //index.js function App() { const choices = [] for (let i = 1; i < 101; i++) { ...

How can I implement SSO and Auth for multiple sub-domains using PHP?

Is it possible to implement SSO using PHP between two different sub-domains (e.g. parappawithfries.com and *.parappawithfries.com)? My current configuration is causing issues as I use Cloudflare to direct my subs to a different 000webhost website. While I ...

Retrieve the ID of the image element using Jquery from a collection of images within a div container

I'm encountering a simple issue that I can't seem to solve. I am working on a basic slider/gallery with the following functionalities: 1) "If button 1 is clicked, image one will appear." 2) "Clicking on button 2 will make IMAGE 1 slide left and I ...

Are there any significant advantages other than SEO for CSR + SSR web applications like nuxtjs and nextjs?

Is the main advantage of implementing SSR + CSR for SEO purposes? When you consider it, SSR actually slows down the initial load time because you have to wait for the server to render and respond with the HTML + JS, requiring a nodejs server with complex c ...

How can I trigger a click event on a link using JQuery?

One of my links has the unique id: nyhedsklik There is a function associated with this link that activates when it is clicked: $('a.poplight[href^=#]').click(function() { var popID = $(this).attr('rel'); //Fetching Popup ...

Triggering event within the componentDidUpdate lifecycle method

Here is the code snippet that I am working with: handleValidate = (value: string, e: React.ChangeEvent<HTMLTextAreaElement>) => { const { onValueChange } = this.props; const errorMessage = this.validateJsonSchema(value); if (errorMessage == null ...

Acquiring the underlying code of websites within the local network

In the tool I am creating, it takes a URL as a parameter and retrieves the source code from that URL for analysis. The tool will be hosted on our domain, with the capability of analyzing web pages of sites within our internal network domain. Here is the Jq ...

How to implement server-side rendering in Next.js 14 with GraphQL queries

I recently completed a Next.js project and configured Apollo Client. I integrated it with my components, as shown in my layout.tsx file: import { Inter } from "next/font/google"; import "./globals.css"; import ApolloProviderClient from ...

Creating a multi-level mobile navigation menu in WordPress can greatly enhance user experience and make

Hey there, I am currently in the process of developing a custom WordPress theme and working on creating a mobile navigation system. Although I have managed to come up with a solution that I am quite pleased with after multiple attempts, I have encountered ...