Repository navigation
On-demand image optimization #3395
Replies: 3 comments
|
I found that using NextJs built-in image optimisation will bypass the access control system, and the resized image will be available all the time. It also meant malicious users could mine the protected images by guessing the filename. I think having a built-in image optimisator will help with the above situation. |
|
You can add unjs/ipx relatively easy to your Payload project. Add the following file under import { createIPX, createIPXWebServer, ipxFSStorage, ipxHttpStorage } from 'ipx'
import path from 'path'
export const runtime = 'nodejs'
const payloadBaseUrl = process.env.PAYLOAD_BASE_URL || 'http://localhost:3001'
const cmsDomain = new URL(payloadBaseUrl).origin
const frontendBaseUrl = process.env.FRONTEND_BASE_URL || 'http://localhost:3000'
const ipx = createIPX({
storage: ipxFSStorage({ dir: path.join(process.cwd(), 'media') }),
httpStorage: ipxHttpStorage({ domains: [cmsDomain] }),
alias: { '/cms': payloadBaseUrl },
})
const ipxHandler = createIPXWebServer(ipx)
const routeBase = '/api/ipx'
const corsHeaders = {
'Access-Control-Allow-Origin': frontendBaseUrl,
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
Vary: 'Origin',
}
function toIPXPath(request: Request): Request {
const url = new URL(request.url)
const path = url.pathname.startsWith(routeBase)
? url.pathname.slice(routeBase.length)
: url.pathname
url.pathname = path.startsWith('/') ? path : `/${path}`
return new Request(url, request)
}
export async function GET(request: Request) {
const response = await ipxHandler(toIPXPath(request))
const headers = new Headers(response.headers)
for (const [key, value] of Object.entries(corsHeaders)) {
headers.set(key, value)
}
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
})
}
export async function OPTIONS() {
return new Response(null, {
status: 204,
headers: corsHeaders,
})
}Some notes:
|
|
I think there's a missing topic of conversation here. Choosing to set pre-determined sizes for media generated at upload time comes with some benefits. The problem with that feature is it is completely under baked. The most common scenario for a CMS is that different content types will display their images in your front-end differently. You may have a 'gallery' content type that is full screen images and a 'team member' content type that shows a small thumbnail image. it is inefficient to store hi-res images for 'team member' photos that get rendered at 256x256, but the current setup requires that. Since you can't attach media directly to documents, your only work around is to create multiple media collections, one for each collection that requires media. This is too much overhead. We need a better solution, one of which is dynamically resized images, but the other is setting image sizes per content type. In this scenario when the media is referenced by a document of type 'team member' (for example) it gets images generated at the image sizes defined by that collection type. |
Uh oh!
There was an error while loading. Please reload this page.
Hi,
I propose Payload to have some kind of built-in image optimization that runs on-demand. This would be similar to what Next Image does. Or maybe IPX is the closest implementation: https://www.npmjs.com/package/ipx.
My problem with current approach is that I need wide spectrum of image dimensions and most of the times, I do not need all of the variations.
What do you think?
All reactions