nuxt / image

Plug-and-play image optimization for Nuxt applications.
https://image.nuxt.com
MIT License
1.28k stars 253 forks source link

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

Open Striffly opened 4 weeks ago

Striffly commented 4 weeks ago

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 commented 4 weeks ago

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

danielroe commented 4 weeks ago

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.

Striffly commented 4 weeks ago

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 ?

danielroe commented 4 weeks ago

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

lukszy commented 2 weeks ago

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?