withastro / adapters

Home for Astro's core maintained adapters
64 stars 33 forks source link

`compiled` image option should create passthrough endpoint for built files #266

Closed bholmesdev closed 1 month ago

bholmesdev commented 4 months ago

Astro Info

Astro                    v4.8.4
Node                     v20.13.1
System                   macOS (arm64)
Package Manager          pnpm
Output                   hybrid
Adapter                  @astrojs/cloudflare
Integrations             @astrojs/markdoc
                         astro-icon

Describe the Bug

I am building a blog with Cloudflare workers and Astro content collections. Migrating from a static setup to SSR, I wanted to preserve image optimization. Content collections are processed at build time so I can luckily use Sharp during the build to avoid issues in SSR. However, Cloudflare's compiled image service doesn't quite support this pattern at runtime.

My setup:

The build succeeds running sharp locally as expected. However, Astro generates image path to resolves to an SSR endpoint (<img src="/_image?href=/_astro/image.png"), rather than the built path (<img src="/_astro/image.png").

What's the expected result?

I expect Astro to output this endpoint route (/_image) since I am not using the prerender flag. However, it would be nice of the Cloudflare integration added a proxy endpoint that routed request to _image to the appropriate entry in dist/. I added this proxy to my own setup using the image.endpoint option to resolve the issue. Here is the implementation:

// src/pages/image-passthrough.ts
import type { APIRoute } from "astro";

export const prerender = false;

export const GET: APIRoute = (ctx) => {
  const href = ctx.url.searchParams.get("href");
  if (!href) {
    return new Response("Missing 'href' query parameter", { status: 400 });
  }

  if (import.meta.env.PROD && !href.startsWith("/_astro")) {
    return new Response("Invalid 'href' query parameter", { status: 400 });
  }

  return fetch(new URL(href, ctx.url.origin));
};

Injecting this would make imageServer: 'compiled' the perfect option for content collection users, since it would unlock SSR rendering as well.

Note: I attempted to make a reproduction in Stackblitz... but I couldn't get a project to build using the cloudflare adapter. I just see a hang and no dist output 😬

Link to Minimal Reproducible Example

https://github.com/bholmesdev/bholmesdev/blob/astro-v4/astro.config.mjs#L17

Participation