Using Astro Image Optimization Benefits with Tina CMS Cloud in Production build

RMAG news

Problem Statement

In production, the benefits of image optimization using Astro’s Image/Picture component are lost when integrating with Tina CMS and Tina Cloud. However, I have found a workaround to resolve this issue. Whether this workaround is the best or a good fit for client websites remains uncertain, but here are the details. For further context, you can read the github discussion here.

Preface

Typically, you have a markdown file with an image path pointing to a locally based image, like so:

imgSrc: /src/assets/img/logo.png

To leverage the image optimization benefits of the Astro Image component, such as generating multiple versions of an image based on device density, you would use dynamic image imports as described in astro docs. Everything works perfectly in development mode when you run npm run “tinacms dev -c “astro dev””,. But for clarity here an example of importing images dynamically.


import type { ImageMetadata } from astro;
import { Image } from astro:assets;

interface Props {
imgSrc: string;
}

const { imgSrc } = Astro.props;

const images = import.meta.glob<{ default: ImageMetadata }>(/src/assets/img/*.{jpeg,jpg,png,gif});

if (!images[imgSrc]) {
throw new Error(`”${imgSrc}” does not exist in glob: “src/assets/img/*.{jpeg,jpg,png,gif}”`);
}

<Image
width=70
height=70
src={images[imgSrc]()}
alt=test image
densities={[1.5, 2]}
loading=lazy
/>

The Production Issue

In production, Tina CMS typically retrieves its media from its own CDN server (e.g., https://assets.tina.io/image). This setup conflicts with Astro’s automatic image optimization and the associated glob pattern.

The function tries to search for the image in the local path. This works in development mode, but in production, the imgSrc returned from the markdown file is no longer a local string. Instead, it returns a URL like https://assets.tina.io/image, causing the search function aka glob function to fail and resulting in a build error.

For more information, refer to the github discussion here.

Workaround for Using Image Optimization

To still leverage Astro’s image optimization in production, you need to adapt the build script:

Modified Build Script

The build script must be updated to:

“scripts”: {
“build”: “tinacms build –local -c astro build
}

However, be aware that dynamically fetching data will no longer work as expected. For example, querying dynamic data using Tina’s client in for example a Date component will not working properly.

Example script of my dynamically data fetches

<script>
import { formatMarkdownUrl, formatDateString } from ../utils/format;

document.addEventListener(DOMContentLoaded, async () => {
try {
const { client } = await import(
../../tina/__generated__/client
);

async function getLiveDatesResponse() {
try {
const response =
await client.queries.live_dateConnection({
sort: date,
});
return response;
} catch (error) {
console.error(
error,
);
return null;
}
}

}
})
</script>

Conclusion

This workaround allows you to leverage Astro’s image optimization benefits in production while using Tina CMS and Tina Cloud. However, it introduces limitations in dynamically fetching data, which may not be suitable for all use cases. Evaluate whether this approach fits your project’s requirements and constraints.

For further reading and to join the discussion, check out the GitHub discussion.