#Download externally-hosted images for SSG.

23 messages · Page 1 of 1 (latest)

sacred horizon
#

Can I somehow download images from a CDN on build time to some folder (such as src/images or /public) and then serve those images statically, without the final render of the <img> elements referencing the CDN instead of the site itself?

gray spireBOT
#

Hi @sacred horizon. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro does not provide a built-in feature to download images from a CDN during build time. However, Astro does support using images from a CDN. You can use an image’s full URL as the src attribute in an <img> tag or Markdown notation. If the CDN provides a Node.js SDK, you can use that in your project. For example, Cloudinary’s SDK (https://cloudinary.com/documentation/node_integration) can generate the <img> tag with the appropriate src for you ^source^ (https://docs.astro.build/en/guides/images#using-images-from-a-cms-or-cdn).

If you want to serve images statically, you can store them in the src/assets/ directory. Astro will recognize this as your new assets folder. Your images can be used by components (.astro, .mdx, and other UI frameworks) and in Markdown files ^source^ (https://docs.astro.build/en/guides/assets#move-your-images-to-srcassets).

If you want to serve images from a different domain than the current site, you can use the build.assetsPrefix configuration option. For example, if this is set to <https://cdn.example.com,> assets will be fetched from <https://cdn.example.com/_astro/...> ^source^ (https://docs.astro.build/en/reference/configuration-reference#buildassetsprefix).

Please note that downloading images from a CDN during build time and storing them locally would require a custom script or tool outside of Astro's built-in capabilities.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@sacred horizon kapa.ai is still learning and improving, please let us know how it did by reacting below

sacred horizon
#

@gray spire According to the documentation @ https://docs.astro.build/en/guides/assets/#getimage-astroassets I can fetch a remote image on the frontmatter (which is run on build), and the result is an object that has a URL 'src' attribute which points to an optimized (cropped, or lower quality, etc.) image.

Won't this be able to do what I was looking towards doing?

Astro Documentation

Learn how to enable experimental asset support in Astro.

gray spireBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The getImage function from @astrojs/image is indeed a helper function used to build <img /> attributes for the transformed image. This helper can be used directly for more complex use cases that aren’t currently supported by the <Image /> component. It takes in an object with the same properties as the <Image /> component and returns an object with attributes that should be included on the final <img /> element ^source^ (https://docs.astro.build/en/guides/integrations-guide/image#getimage).

However, it's important to note that getImage is used for image optimization and transformation, not for downloading or storing images. It doesn't download the image to a local directory. Instead, it returns an object with the src attribute pointing to the optimized image, which can be used in the src attribute of an <img /> tag.

Here's an example of how you can use getImage:

---
import { getImage } from '@astrojs/image';

const { src } = await getImage({
 src: import('../assets/hero.png'),
 alt: 'My hero image',
});
---

<html>
 <head>
 <link rel="preload" as="image" href={src} alt="alt text" />
 </head>
</html>

In this example, getImage is used to optimize the image and return the src attribute for the optimized image. This src is then used in a link tag for preloading the image.

So, while getImage can help with image optimization and transformation, it doesn't provide a built-in way to download images from a CDN to a local directory during build time.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@sacred horizon kapa.ai is still learning and improving, please let us know how it did by reacting below

sacred horizon
#

But @gray spire , where is the optimized image hosted then, if not locally?

gray spireBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The optimized image is hosted in the dist/_astro folder in your project. When you build your Astro project, it creates a dist directory with your built site. This includes any assets that Astro has processed, such as optimized images.

For local images, Astro's built-in image optimization will transform, optimize, and bundle them into the dist/_astro directory ^source^ (https://docs.astro.build/en/guides/images#public).

For images stored in the public/ directory, the original image will be copied unprocessed to the build folder, and Astro’s image integration will also return optimized versions of the image ^source^ (https://docs.astro.build/en/guides/integrations-guide/image#images-in-public).

For remote images, Astro fetches the image, optimizes it, and then stores the optimized version in the dist/_astro directory. The src attribute returned by getImage points to the location of the optimized image in the dist/_astro directory ^source^ (https://docs.astro.build/en/guides/integrations-guide/image#getimage).

Please note that the dist/_astro directory is created when you build your Astro project, so the optimized images won't be available in your project directory until after you've run the build command.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@sacred horizon kapa.ai is still learning and improving, please let us know how it did by reacting below

sacred horizon
#

@gray spire then this effectively solves my problem, as contrary to what you said before, Astro does indeed fetch the remote image (to optimize it) and then makes it available via the 'dist/_astro' folder. Or am I misunderstanding something?

gray spireBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Yes, you're correct. I apologize for the confusion. Astro does fetch remote images, optimizes them, and then makes them available in the dist/_astro directory. This is done during the build process when you use the getImage function from @astrojs/image ^source^ (https://docs.astro.build/en/guides/integrations-guide/image#getimage).

Here's an example of how you can use getImage to fetch and optimize a remote image:

---
import { getImage } from '@astrojs/image';

const { src } = await getImage({
 src: '<https://example.com/image.jpg',>
 alt: 'My image',
});
---

<img src={src} alt="My image" />

In this example, getImage fetches the image from the provided URL, optimizes it, and returns an object with the src attribute for the optimized image. This src is then used in an <img /> tag. The optimized image will be stored in the dist/_astro directory in your project.

So, yes, Astro does provide a way to fetch remote images, optimize them, and serve them statically from your site. I apologize for the oversight in my previous responses.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@sacred horizon kapa.ai is still learning and improving, please let us know how it did by reacting below

sacred horizon
#

@gray spire I'm getting the following errors:

"MissingImageDimension: Missing width and height attributes for https://files.stripe.com/links/link-id. When using remote images, both dimensions are always required in order to avoid CLS.
...
title: 'Missing image dimensions',
hint: 'If your image is inside your src folder, you probably meant to import it instead. See the Imports guide for more information.',
frame: undefined,
type: 'AstroError'"

In my code, I have:

import { Image, getImage } from 'astro:assets';

const astroImg = await getImage({
    src: productResponse.images[0],
    alt: 'Meal bowl example',
});

in the front-matter, and:

<Image
            src={ astroImg }
            alt="Meal bowl example"
            width="264"
            height="264"
            class="rounded-lg"
        />

in the HTML...

gray spireBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error message you're seeing is due to missing width and height attributes for remote images. When using remote images, both dimensions are always required in order to avoid cumulative layout shift (CLS) ^source^ (https://docs.astro.build/en/reference/errors/missing-image-dimension/).

In your code, you're using getImage to fetch and optimize a remote image, and then using the Image component to display the image. However, you're passing the entire object returned by getImage to the src attribute of the Image component. The src attribute should be a string representing the URL of the image, not an object.

Here's how you can fix this:

import { Image, getImage } from 'astro:assets';

const astroImg = await getImage({
    src: productResponse.images[0],
    alt: 'Meal bowl example',
    width: 264,
    height: 264,
});

<Image
    src={astroImg.src}
    alt="Meal bowl example"
    width="264"
    height="264"
    class="rounded-lg"
/>

In this corrected code, astroImg.src is passed to the src attribute of the Image component, which is the URL of the optimized image. The width and height are also specified in the getImage function to avoid the MissingImageDimension error.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@sacred horizon kapa.ai is still learning and improving, please let us know how it did by reacting below

delicate canopy
#

This thread was really helpful since I had the same issue.

@gray spire is it possible to customise the names of the remote images that are fetched?

gray spireBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Astro does not provide a built-in feature to customize the names of remote images that are fetched and optimized. When Astro fetches and optimizes a remote image, it generates a unique filename for the optimized image based on the image's content and the optimization options. This ensures that each unique image and set of options has a unique filename, which is important for caching and performance.

However, you can customize the output filenames for code that Astro processes, like imported JavaScript or CSS files, using entryFileNames, chunkFileNames, and assetFileNames in a vite.build.rollupOptions entry in your astro.config.* file ^source^ (https://docs.astro.build/en/guides/configuring-astro/#customising-output-filenames).

Here's an example:

import { defineConfig } from 'astro/config'
export default defineConfig({
  vite: {
    build: {
      rollupOptions: {
        output: {
          entryFileNames: 'entry.[hash].mjs',
          chunkFileNames: 'chunks/chunk.[hash].mjs',
          assetFileNames: 'assets/asset.[hash][extname]',
        },
      },
    },
  },
})

In this example, entryFileNames, chunkFileNames, and assetFileNames are used to customize the output filenames for entry chunks, non-entry chunks, and other assets respectively. The [hash] placeholder is replaced with a hash based on the file's content, and the [extname] placeholder is replaced with the file's extension.

Please note that this configuration does not affect the filenames of remote images fetched and optimized by Astro. The filenames of these images are determined by Astro and cannot be customized.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: