image icon indicating copy to clipboard operation
image copied to clipboard

Images aren't being retrieved from Strapi provider when using `nuxt generate`

Open Striffly opened this issue 1 year ago • 10 comments

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

  1. Install & configure nuxt-image
  2. Run nuxt generate

Demo

https://stackblitz.com/edit/nuxt-image-ebldlk

Striffly avatar May 27 '24 23:05 Striffly

@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?

Striffly avatar May 29 '24 14:05 Striffly

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.

danielroe avatar May 29 '24 14:05 danielroe

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 ?

Striffly avatar May 29 '24 15:05 Striffly

Exactly. Remote images can also be optimised but not if they are paired with a runtime provider.

danielroe avatar May 29 '24 16:05 danielroe

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?

lukszy avatar Jun 06 '24 11:06 lukszy

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.

gridsystem avatar Jul 31 '24 14:07 gridsystem

That's a great idea.

danielroe avatar Aug 14 '24 11:08 danielroe

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.

@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 avatar Oct 01 '24 17:10 gridsystem

@gridsystem would you be interested in contributing to the docs with your previous comment? :)

Baroshem avatar Dec 12 '24 07:12 Baroshem

@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.

gridsystem avatar Jan 12 '25 14:01 gridsystem