-
Notifications
You must be signed in to change notification settings - Fork 83
Description
Is your feature request related to a problem? Please describe.
I’m trying to display an image served from my NuxtHub blob, as explained here. While it works perfectly with a standard tag, the image doesn’t show up when I use
<NuxtImg>.
The default ipx provider of <NuxtImg> doesn't work since the image is returned from an api path.
The none provider works fine like <img> but the image is returned as is.
The cloudflare provider works but only in production, when the website served by cloudflare. (In deployed development could work but with any origin activated and specifying the production url as the base url of the provider)
Describe the solution you'd like
Would be nice to have a nuxthub provider (or maybe a <NuxtHubImg>) that permits to leverage <NuxtImg> out-of-the-box.
Describe alternatives you've considered
For now since Cloudflare Images doesn’t provide a way to set images when working locally, I created a provider that uses Cloudflare Images in production and falls back to the original R2 image in development.
nuxt.config.ts
nuxt.config.ts image: {
providers: {
cloudflareOnProd: {
provider: '~/providers/cloudflareOnProd.ts',
options: {
prodSiteURL: 'https://example.com'
}
}
}
}
cloudflareOnProd.ts
cloudflareOnProd.ts import type { ProviderGetImage } from '@nuxt/image'
import { getImage as getImageWithCloudflare } from '#image/providers/cloudflare'
import { getImage as getImageWithNone } from '#image/providers/none'
export const getImage: ProviderGetImage = (src, options, ctx) => {
if (useRuntimeConfig().public.siteURL === options.prodSiteURL) {
return getImageWithCloudflare(src, options, ctx)
} else {
return getImageWithNone(src, options, ctx)
}
}
Legacy
cloudflareOnProd.ts
cloudflareOnProd.tsimport { joinURL, encodeQueryItem } from 'ufo'
import type { ProviderGetImage } from '@nuxt/image'
import { createOperationsGenerator } from '#image'
const operationsGenerator = createOperationsGenerator({
keyMap: {
width: 'w',
height: 'h',
dpr: 'dpr',
fit: 'fit',
gravity: 'g',
quality: 'q',
format: 'f',
sharpen: 'sharpen',
},
valueMap: {
fit: {
cover: 'cover',
contain: 'contain',
fill: 'scale-down',
outside: 'crop',
inside: 'pad',
},
gravity: {
auto: 'auto',
side: 'side',
},
},
joinWith: ',',
formatter: (key, val) => encodeQueryItem(key, val),
})
const defaultModifiers = {}
// https://developers.cloudflare.com/images/image-resizing/url-format/
export const getImage: ProviderGetImage = (src, {
modifiers = {},
baseURL = '/',
prodSiteURL
} = {}) => {
const mergeModifiers = { ...defaultModifiers, ...modifiers }
const operations = operationsGenerator(mergeModifiers as any)
let url
if (useRuntimeConfig().public.siteURL === prodSiteURL) {
// https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>
url = operations ? joinURL(baseURL, 'cdn-cgi/image', operations, src) : joinURL(baseURL, src)
} else {
url = joinURL(baseURL, src)
}
return {
url
}
}