dc7290 / next-export-optimize-images

Optimize images at build time with Next.js.
https://next-export-optimize-images.vercel.app
MIT License
368 stars 34 forks source link

Downloaded external images not being inserted into `<Image />` component `src` values #862

Open beschler opened 2 months ago

beschler commented 2 months ago

Hi there - I'm following up on issue #824 - I see you have issued a new release to address my problem. Thank you so much! My export-images.config.js configuration file is now running as expected.

My follow-up question is this: My (external) images are stored on an AWS S3 bucket, which is private, so the only way to access the files is by generating pre-signed URLs. I set this up in my export-images.config.js configuration file, using the remoteImages configuration option to build an array of pre-signed image URLs:

module.exports = {
  remoteImages: async () => {
    const imageUrls = await getStaticImages();
    return imageUrls;
  },
};

(I posted the full code in issue #824.)

With v4.3.1, this successfully downloads the images and places them into the /out folder of Next.js. It seems they go in two folders:

  1. /out/_next/static/media/{a_random_hash}.jpg
  2. /out/_next/static/chunks/images/{original_filename}_{size}.jpg

Your documentation for external images states that my <Image /> tags will be converted into something like:

<img
  srcset="/_next/static/chunks/images/og_1920_75.png 1x, /_next/static/chunks/images/og_3840_75.png 2x"
  src="/_next/static/chunks/images/og_3840_75.png"
/>

However, this is not happening. The resulting <img /> tags are unchanged.

I suspect this is due to the fact that, in my code for the pages outputting the <Image /> components, the src is also generating a pre-signed URL for the AWS S3 bucket images, and each of these URLs are unique each time they're generated. For example, the output is something like this:

https://{MYAWSBUCKET}.s3.{REGION}.amazonaws.com/{FILENAME}.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential={RANDOMLY_GENERATED_CREDENTIALS}&X-Amz-Date={DATE_GENERATED_TIMESTAMP}&X-Amz-Expires={EXPIRATION_TIME}&X-Amz-Signature={RANDOMLY_GENERATED_SIGNATURE_STRING}&X-Amz-SignedHeaders=host&x-id=GetObject

Everything after the ? in the filename is unique to that run, and I suspect because the URLs in the code don't exactly match the URLs generated by export-images.config.js (they'll have different URL parameters, a different {DATE_GENERATED_TIMESTAMP}, {RANDOMLY_GENERATED_CREDENTIALS}, etc.), that the src values are not being replaced to the /_next/static/chunks/images/... download URLs.

I tried to test this theory with a solution that involved leveraging the sourceImageParser option, as such:

module.exports = {
  sourceImageParser: ({ src, defaultParser }) => {
    let srcPieces = src.split("?");
    let srcData = [];
    if (srcPieces.length > 1) {
      srcData = srcPieces[0];
      srcData = srcData.replace(`https://{MYAWSBUCKET}.s3.{REGION}.amazonaws.com/`, ``);
      srcData = srcData.split(".");
    }
    if (srcData.length < 2) {
      return defaultParser(src);
    }
    return {
      pathWithoutName: "",
      name: srcData[0] || "",
      extension: srcData[1] || "",
    };
  },
  remoteImages: async () => {
    const imageUrls = await getStaticImages();
    return imageUrls;
  },
};

This strips the URL parameters generated by the AWS S3 URL pre-signing process, and always returns just the filename and extension. However this didn't solve my problem: images are downloaded successfully with the next build && next-export-optimize-images command and placed in the two folders inside /out/_next/static/... folders as expected, but all <Image /> src values have not been updated to their optimized values, something like:

<img
  srcset="/_next/static/chunks/images/og_1920_75.png 1x, /_next/static/chunks/images/og_3840_75.png 2x"
  src="/_next/static/chunks/images/og_3840_75.png"
/>

Instead, the <Image /> src values are set as the pre-signed URLs at the time of the next build process.

You know your code best - can you guide me to how I can display these images download by next-export-optimize-images into my <Image /> components?

(NOTE: I did update my Next.js version to 14.2.2, and next-export-optimize-images version to 4.3.1, and replaced my import statements for the Image component to next-export-optimize-images/image instead of next/image.)

I really appreciate all your help! 🙏🏻

dc7290 commented 1 month ago

Do you mean that the src attribute of the img tag is not as expected when using sourceImageParser? We would be grateful if you could make a reproducible sample using CodeSandbox or similar.