withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.31k stars 2.45k forks source link

@astrojs/image works locally but not on Vercel #5253

Closed tycol7 closed 1 year ago

tycol7 commented 1 year ago

What version of astro are you using?

1.6.1

Are you using an SSR adapter? If so, which one?

Vercel

What package manager are you using?

pnpm 7.14.1

What operating system are you using?

Mac

Describe the Bug

What

@astrojs/image + Cloudinary photo gallery builds locally but not in Vercel.

Steps to reproduce

  1. Sign up for Cloudinary free tier
    • Set CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, and CLOUDINARY_API_SECRET in .env
  2. Build linked Minimal Reproducible Example locally using npm run build

    • Should finish successfully

      optimizing 27 images in batches of 8
      08:39:48 AM [build] Waiting for the @astrojs/image integration...
      Completed in 350.94s.
      
      Completed in 351.82s.
  3. Sign up for Vercel and create a Github-linked project
    • Set Cloudinary environment variables from Step 1 in the Domain Settings
  4. Push the Minimal Reproducible Example to Github
  5. Observe the timeout failure in Vercel's build output log
    07:38:37.742 | optimizing 27 images in batches of 4
    07:38:40.713 | 02:38:40 PM [build] Waiting for the @astrojs/image integration...
    07:53:39.030 | Error: Command "npm run build" exited with SIGKILL

Initial thoughts

I understand @astrojs/image is still experimental. I don't think I'm using @astrojs/vercel/edge in my project. Wondering if I'm doing something wrong or if this implementation is not yet supported.

Thank you for any advice!

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-zugjfz?file=src/components/PhotoGallery.astro

Participation

tycol7 commented 1 year ago

Fixed the build issue by installing vercel package.

Now the <Pictures> get a 500 error with the following message:

ERROR   Uncaught Exception  {"errorType":"Error","errorMessage":"Cannot find module '/var/task/node_modules/@astrojs/image/dist/vendor/squoosh/image-pool.js'","code":"MODULE_NOT_FOUND","requireStack":[],"stack":["Error: Cannot find module '/var/task/node_modules/@astrojs/image/dist/vendor/squoosh/image-pool.js'","    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)","    at Function.Module._load (node:internal/modules/cjs/loader:778:27)","    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)","    at MessagePort.<anonymous> (node:internal/main/worker_thread:191:24)","    at MessagePort.[nodejs.internal.kHybridDispatch] (node:internal/event_target:643:20)","    at MessagePort.exports.emitMessage (node:internal/per_context/messageport:23:28)"]}
Unknown application error occurred

Also, an image I have locally in the src/assets folder breaks when changing from static to SSR, so the problem is not with Cloudinary.

mandar1jn commented 1 year ago

I’ve also seen reports of the image integration breaking down when using netlify

tycol7 commented 1 year ago

Chatted with support and seems this is a known issue. Building locally to dist/ and dragging and dropping the output folder into Netlify works - any astrojs/image-SSR integration with either Vercel or Netlify does not.

tony-sull commented 1 year ago

Looks like it may be an issue with how the Squoosh .wasm binaries are copied over during the Vercel build 🤔

As a work around, if you're deploying to a NodeJS environment you should be able to install sharp and update the integration to use that instead of Squoosh,

import image from '@astrojs/image'

export default defineConfig({
    integrations: [
        image({ serviceEntryPoint: '@astrojs/image/sharp' })
    ],
});
tycol7 commented 1 year ago

Looks like it may be an issue with how the Squoosh .wasm binaries are copied over during the Vercel build 🤔

As a work around, if you're deploying to a NodeJS environment you should be able to install sharp and update the integration to use that instead of Squoosh,

import image from '@astrojs/image'

export default defineConfig({
  integrations: [
      image({ serviceEntryPoint: '@astrojs/image/sharp' })
  ],
});

Closer! Most GET requests now timeout after 10 seconds. Oddly, 1/25 Cloudinary photos made it through. The local asset also times out.

[GET] /_image?f=avif&w=2448&h=1632&href=https%3A%2F%2Fres.cloudinary.com%2Fduk2eltbv%2Fimage%2Fupload%2Fv1667090657%2FDSCF0339_icdfnu.jpg
07:32:46:47
2022-10-31T14:32:56.773Z d204e009-e82d-480a-926e-4c0eb4a58471 Task timed out after 10.04 seconds
kyr0 commented 1 year ago

@tycol7 btw, I'm having the same issue; I was working on an alternative Image component that allows for a local build and Vercel Remote Cache upload/download; this way the Remote Cache would be downloaded in CI (because it as been fully populated in a local build) and all the images will be there without an actual sharp or squoosh usage in CI. It would also increase build speed in CI. It's not optimal and of course, would be essential to have the image optimization step working in CI too, but it would at least work for now... pls tell me if you're interested, then I'll keep you posted.

Btw:; How do you generate the Cloudinary link? Do you just copy the whole link from Cloudinary and use it in <Image />? Because I'm also working on a <Cloudinary /> Astro component ;)

tycol7 commented 1 year ago

pls tell me if you're interested, then I'll keep you posted.

That'd be great - let me know how it goes!

Btw:; How do you generate the Cloudinary link? Do you just copy the whole link from Cloudinary and use it in <Image />? Because I'm also working on a <Cloudinary /> Astro component ;)

I'm just getting the URL and passing that to a <Picture> element. But since it's not working, I might just generate the entire <img> from Cloudinary and apply the optimizations in the URL itself (e.g. https://res.cloudinary.com/duk2eltbv/image/upload/dpr_auto/f_auto/q_auto/cld-sample.jpg)

---
import { v2 as cloudinary } from 'cloudinary';
import { Picture } from '@astrojs/image/components';

cloudinary.config({
    cloud_name: import.meta.env.CLOUDINARY_CLOUD_NAME,
    api_key: import.meta.env.CLOUDINARY_API_KEY,
    api_secret: import.meta.env.CLOUDINARY_API_SECRET,
    secure: true,
});

const cloudinary_search = await cloudinary.search
    .expression('folder:tylerd-co')
    .with_field('context')
    .sort_by('uploaded_at', 'desc')
    .execute();

const images = cloudinary_search.resources;
---

<main class="mt-24">
    <div>
        {
            images.map((image: any) => (
                <div class="mb-8">
                    <Picture
                        src={image.secure_url}
                        widths={[image.width / 4, image.width / 2, image.width]}
                        sizes={`(max-width): ${image.width} 100vw, ${image.width}`}
                        aspectRatio={image.aspect_ratio}
                        alt={image.context ? image.context.alt : "" }
                    />
                </div>
            ))
        }
    </div>
</main>
Maxime-p commented 1 year ago

I'm having a similar issue with render.com (image integration breaking)

Is it related or do I need to create a new issue ?

alidcast commented 1 year ago

seems to only work when running astro dev, not astro build

Maxime-p commented 1 year ago

seems to only work when running astro dev, not astro build

The path generated in the code doesn't correspond to the path in of the assets

matthewp commented 1 year ago

Looking into this now to see if there's something we can do in the short term.

matthewp commented 1 year ago

Fixed in main, this should go out later today.

matthewp commented 1 year ago

Had to revert the fix to this as it broke other usages. Shouldn't take long to refix this though.

matthewp commented 1 year ago

Fixed in https://github.com/withastro/astro/pull/5361

alexkazachkov commented 1 year ago

I forgot to give my component in Astro the format types for the remote images. After analysing the code, I found out that the AVIF format is the one which gets stuck/leads to the timeouts.

So this is what works for me with almost no delay:

<Picture
    src={image}
    widths={[352, 400, 704, 800, 1056, 1600]}
    sizes="22rem"
    aspectRatio="851:1200"
    format="png"
    formats={['webp', 'png']}
    width={352}
    height={496}
    loading="eager"
    alt="Example Alt"
/>

I have left out jpeg and avif from formats={['webp', 'png']}, as jpeg is rendered when format="jpeg" is set (when set to format="png", then no jpeg is created), and avif is the one format that just doesn't really want to work quickly with Astro and the functions.

mahmood601 commented 7 months ago

I have the same issue and I use astro:assets

JenuelDev commented 2 months ago

Si their a fix for this one?

JenuelDev commented 2 months ago

So in my case the vercel return an error message about sharp image

So I installed it, and then pushed it to my repo for redeployment, And it works.

vintageplayer commented 2 months ago

This worked for me: https://docs.astro.build/en/reference/errors/missing-sharp/

kyr0 commented 2 months ago

@vintageplayer Yeah, because it does nothing :D If nothing happens, nothing can break :) 💯 https://github.com/withastro/astro/blob/8118120e91ba9497f98f6a95511b9d401ffd7299/packages/astro/config.mjs#L20