Images aren't being retrieved from Strapi provider when using `nuxt generate`
Hi,
I want to generate static images with Strapi as the provider. For this, I use the nuxt generate command, which normally retrieves the images from my provider and adds them locally.
However, my .output folder does not contain these images, and the image URLs are not updated in generated HTML.
Expected Behavior
Get images from Strapi added to assets/images folder, and images URLs updated to query images from assets/images folder and not Strapi
Current Behavior
Images are not retrieved from Strapi, and images urls are not updated
Steps to Reproduce
- Install & configure
nuxt-image - Run
nuxt generate
Demo
https://stackblitz.com/edit/nuxt-image-ebldlk
@danielroe Isn't it more of a bug than an enhancement? Generating and optimizing images for a static build from the provider is one of the key features of nuxt-image, if I'm not mistaken?
Nuxt Image supports static image optimisation using ipx; it doesn't currently do static optimisation of images from a runtime provider, though I think it would be a nice enhancement.
Ok, so if I understand correctly, currently the image URLs necessarily point to the provider, and the optimization (media sizes, webp / avif) must be done by the provider. Only images hosted locally (thus directly in the Nuxt project) can be optimized throught IPX. Is that correct ?
Exactly. Remote images can also be optimised but not if they are paired with a runtime provider.
Have the same issue with Strapi. Got a small workaround creating a new provider that runs only on 'prerender' (nuxt generate) phase.
Its not perfect but so far it's the best i could come up with
import { type ProviderGetImage } from "@nuxt/image";
import axios from "axios";
import fs from "node:fs";
import * as ufo from "ufo";
const OUTPUT_DIR = '.output';
const PUBLIC_DIR = 'public';
function pullImageAndSave(remoteURL: string, distDir: string) {
return axios({
method: "GET",
url: remoteURL,
responseType: "stream",
})
.then((response) => response.data.pipe(fs.createWriteStream(distDir)))
.catch((error) => {
console.error(`Could not load image ${remoteURL}`);
});
}
export const getImage: ProviderGetImage = (
src,
{ baseURL, localDir } = {},
) => {
const dir = ufo.joinURL(OUTPUT_DIR, PUBLIC_DIR, localDir);
const remoteURL = ufo.joinURL(baseURL, src);
// return remote path for development
if (process.env.NODE_ENV === 'development') {
return {
url: remoteURL,
};
}
const filename = src.split("/").pop();
const distUrl = ufo.joinURL(localDir, filename!);
if (process.env.NODE_ENV === 'prerender') {
if (!fs.existsSync(dir)) {
try {
fs.mkdirSync(dir, { recursive: true });
} catch (error) {
console.log(error);
}
}
if (filename) {
const distDir = ufo.joinURL(dir, filename);
pullImageAndSave(remoteURL, distDir);
}
}
return {
url: distUrl,
};
};
But it has one downside, pullImageAndSave is async, used in sync code which causes the nuxt generate to be freeze at the end - i guess its because the script is still pulling the images after the prerender was done.
@danielroe maybe you have an idea how to fix that?
Can I suggest updating the static images section of the docs to be clearer about this?
I also misunderstood this to mean that images would be transformed by image providers, and cached locally with the generated site to deploy.
I was surprised that it wasn't working that way.
It took me a while to find the right search term to find an issue mentioning that it's not the intended behaviour.
That's a great idea.
But it has one downside,
pullImageAndSaveis async, used in sync code which causes thenuxt generateto be freeze at the end - i guess its because the script is still pulling the images after the prerender was done.
@lukszy Did you manage to sort out the freezing issue? I'm quite interested in using something like this so that I can have a self-contained backup of my site which uses Directus as an image provider. It would be cool to have a copy of the site that doesn't depend on running an instance of the CMS.
I'm not familiar with creating a provider - how would I use your provider code in a Nuxt app, assuming I was using Strapi?
@gridsystem would you be interested in contributing to the docs with your previous comment? :)
@Baroshem I've just seen this and had a go at putting together a few words. I've realised that I am not the best person to do the job as I've never used the local images provider.
I'm a bit confused by wording under Default provider and don't understand where the line is between local images that are cached and remote images which are not, as this text implies that some remote images are.