Open maximelebreton opened 1 year ago
I have the same case, and it would be awesome if there were a solution 🙂
any update on this ?
Yeah this is super annoying. The integration of Nuxt with Strapi in general doesn't seem very well documented at all.
Hope there will be an update for this soon.
@PeritonM I switched to cloudinary, that seems to be working and for local images add provider="static"
Hey ya'll,
So after looking into the code what I can surmise is that this is not currently possible and is not technically a bug in the module. What is happening is that by default, Strapi does not provide url parameters to request custom images. However, the module is using the sizes
in the prop to request images using said url parameters and then set the srcset
attribute accordingly. I added a console.log to the module locally to see what the srcset came out to. This is what it was:
srcset
:
"http://0.0.0.0:1337/uploads/image.jpg 128w, http://0.0.0.0:1337/uploads/image.jpg 320w"
As you can see, since Strapi doesn't support query parameters or anything like that, nuxt-image is just using the same image url everytime. I'm considering working on a PR that incorporates this strapi plugin:
https://www.npmjs.com/package/strapi-plugin-local-image-sharp
That should theoretically enable the ability to use sizes with strapi after mapping the parameters to the plugin.. However since this a 3rd party plugin, it doesn't seem ideal. It is also the only foreseeable solution until Strapi includes this functionality by default.
I would love to hear from the nuxt team on this. I would be happy to work on a PR for this functionality.
In the event the above PR doesn't get accepted, I'm posting instructions here for implementing the "local image sharp" plugin as a custom provider in Strapi.
Install the local image sharp
Strapi plugin. https://market.strapi.io/plugins/strapi-plugin-local-image-sharp
Create the file ~/providers/localImageSharp.ts
and inside put:
import { joinURL } from "ufo";
import type { ProviderGetImage } from "@nuxt/image-edge";
import { createOperationsGenerator } from "#image";
export const getImage: ProviderGetImage = (
src,
{ modifiers, baseURL = "http://localhost:1337/uploads" } = {}
) => {
const operationsGenerator = createOperationsGenerator({
keyMap: {
width: "width",
height: "height",
resize: "resize",
fit: "fit",
position: "positon",
trim: "trim",
format: "format",
quality: "quality",
rotate: "rotate",
enlarge: "enlarge",
flip: "flip",
flop: "flop",
sharpen: "sharpen",
median: "median",
gamma: "gamma",
negate: "negate",
normalize: "normalize",
threshold: "threshold",
grayscale: "grayscale",
animated: "animated",
},
joinWith: ",",
formatter: (key: string, value: string) => `${key}_${value}`,
});
const operations = operationsGenerator(modifiers as any);
return {
url: joinURL(baseURL, operations, src),
};
};
nuxt.config.ts
:image: {
providers: {
localImageSharp: {
provider: "~/providers/localImageSharp",
options: {
baseURL: `${process.env.STRAPI_URL}/uploads/`,
},
},
},
provider: 'localImageSharp'
},
sizes
working properly.*Note: The median
modifier doesn't seem to be working. I've raised an issue in the local image sharp
plugin repo.
Also, if you have any ideas on how to improve upon the above code, feel free to chime in of course.
Cheers!
@jiblett1000 Pardon me but what is this file #image in 'import { createOperationsGenerator } from "#image";' ?
Your solution seems perfect but I can't manage to make it work...
Hello @ulysse-lacour . #image
is a directory alias added by the nuxt/image module. Ctrl + clicking on it should bring you to the index file of the image module.
@jiblett1000 Thank you very much, didn't realized I needed both nuxt/image and nuxt/image-edge (if I'm not mistaking)! Set up for provider works like a charm thanks to your instructions, I have a silly question but I think a few beginners like me would really appreciate to make sure they set up cleanly : how can I make sure the sizes are finally working ?
Using this :
<nuxt-img
loading="lazy"
:src="`${post.attributes?.Image?.data?.attributes?.url}`"
sizes="sm:100vw md:100vw lg:100vw"
/>
Render this img tag :
<img src="http://localhost:1337/uploads/width_1024/uploads/SQUARE_IMAGE_e2ad4450a0.png" onerror="this.setAttribute('data-error', 1)" loading="lazy" data-nuxt-img="" sizes="(max-width: 640px) 100vw, (max-width: 768px) 100vw, 100vw" srcset="http://localhost:1337/uploads/width_640/uploads/SQUARE_IMAGE_e2ad4450a0.png 640w, http://localhost:1337/uploads/width_768/uploads/SQUARE_IMAGE_e2ad4450a0.png 768w, http://localhost:1337/uploads/width_1024/uploads/SQUARE_IMAGE_e2ad4450a0.png 1024w">
So it seems to work but weirdly my files in Strapi are named like this small_SQUARE_IMAGE_e2ad4450a0.png/thumbnail_SQUARE_IMAGE_e2ad4450a0 and not with that folder architecture with width in this example.
Hopefully I'm not the ones confused by the names differences and how Strapi is handling images.
@ulysse-lacour
You do not need to install both versions. You can use the rc
release of the @nuxt/image
package.
You can see if it's working by changing the "size" for one of the screen breakpoints and seeing the resulting change in file size / resolution of the requested image. For example, create a fullscreen image and then change the image size in the sizes
prop from say 100vw
to 20vw
and you should see how the image quality is degraded and the file size is less because it's now requesting an image for only 20% of the screen width.
The addition of "width" or whatever modifiers you're using via the nuxt image custom provider above are added to the url by nuxt/image and utilized on the backend (strapi) by the local image sharp plugin to return the correctly sized image.
@ulysse-lacour You might also consider forming your src strings like this:
:src="${image.data.attributes.hash}${image.data.attributes.ext}
"
Depending on how your base url is configured in nuxt/image, this might be necessary so it doesn't add an additional uploads
into the url.
At least I seem to recall having an issue like that before. It's been a bit since I was working on this.
Thank a lot @jiblett1000 you're an absolute chef, it was indeed working, just had to play with sizes attribute to realize it! If you have some ressources in mind to learn more on Nuxt x Strapi integration feel free to share they would be really useful to me :)
@ulysse-lacour No worries. Not sure I can really point you towards any particular resources except for the nuxt/strapi module (if you're not already using it). https://strapi.nuxtjs.org/
@jiblett1000 Thanks again, I've seen it but couldn't see any use cases for this module...
In the event the above PR doesn't get accepted, I'm posting instructions here for implementing the "local image sharp" plugin as a custom provider in Strapi.
- Install the
local image sharp
Strapi plugin. https://market.strapi.io/plugins/strapi-plugin-local-image-sharp- Create the file
~/providers/localImageSharp.ts
and inside put:import { joinURL } from "ufo"; import type { ProviderGetImage } from "@nuxt/image-edge"; import { createOperationsGenerator } from "#image"; export const getImage: ProviderGetImage = ( src, { modifiers, baseURL = "http://localhost:1337/uploads" } = {} ) => { const operationsGenerator = createOperationsGenerator({ keyMap: { width: "width", height: "height", resize: "resize", fit: "fit", position: "positon", trim: "trim", format: "format", quality: "quality", rotate: "rotate", enlarge: "enlarge", flip: "flip", flop: "flop", sharpen: "sharpen", median: "median", gamma: "gamma", negate: "negate", normalize: "normalize", threshold: "threshold", grayscale: "grayscale", animated: "animated", }, joinWith: ",", formatter: (key: string, value: string) => `${key}_${value}`, }); const operations = operationsGenerator(modifiers as any); return { url: joinURL(baseURL, operations, src), }; };
- Add this in your
nuxt.config.ts
:image: { providers: { localImageSharp: { provider: "~/providers/localImageSharp", options: { baseURL: `${process.env.STRAPI_URL}/uploads/`, }, }, }, provider: 'localImageSharp' },
- Sit back and enjoy
sizes
working properly.*Note: The
median
modifier doesn't seem to be working. I've raised an issue in thelocal image sharp
plugin repo.Also, if you have any ideas on how to improve upon the above code, feel free to chime in of course.
Cheers!
thx!!!
You're a hero @jiblett1000. I've been wanting to use nuxt-image for ages, but couldn't quite figure out rolling my own provider with Strapi. Have been rolling my own image component using strapi local image sharp instead.
Hello,
is it the same thing for format props ? It seems that it doesn't work with provider strapi.
Thanks
This provider is intended for those who do not want dynamic image generation and are using the strapi-image-optimizer plugin to create images with multiple breakpoints and formats.
import { withBase, withoutLeadingSlash } from "ufo";
import type { ProviderGetImage } from "@nuxt/image";
// https://strapi.io/documentation/developer-docs/latest/development/plugins/upload.html#upload
export const getImage: ProviderGetImage = (src, { modifiers, baseURL } = {}) => {
const { breakpoints, width, format } = modifiers || {};
let chosenBreakpoint = null;
if (width && breakpoints) {
for (const [key, value] of Object.entries(breakpoints)) {
const bpValue = Number(value);
if (bpValue >= width + 50) {
chosenBreakpoint = { key, value: bpValue };
break;
}
}
}
const breakpointKey = chosenBreakpoint ? chosenBreakpoint.key : "";
if (breakpointKey === "") {
return {
url: withBase(src, baseURL),
};
}
const ext = src.split(".").pop();
const formattedSrc = `${breakpointKey}_${format}_${withoutLeadingSlash(src).replace(`.${ext}`, "")}.${format}`;
return {
url: withBase(formattedSrc, baseURL),
};
};
export const validateDomains = true;
Usage Example
<NuxtPicture
:modifiers="{ breakpoints: { small: '500', medium: '750', large: '1280', full: '1920' } }"
densities="x1"
provider="strapiV2"
sizes="200 xl:1200"
src="background_affisha_f0db2ea4d1.png"
/>
Details src: We pass the hash and extension from Strapi. sizes: Specify the actual sizes on the layout (I implemented it with numbers only, without px). modifiers: Pass our breakpoints in the format { breakpoints: { ... } }. And don't forget to specify the required formats via format or in global settings.
Result You will have automatically generated images like this:
<picture data-v-02281a80="">
<source
type="image/avif"
sizes="(max-width: 1439.9px) 200px, 1200px"
srcset="https://your-strapi-url/uploads/small_avif_background_affisha_f0db2ea4d1.avif 200w, https://your-strapi-url/uploads/large_avif_background_affisha_f0db2ea4d1.avif 1200w"
/>
<source
type="image/webp"
sizes="(max-width: 1439.9px) 200px, 1200px"
srcset="https://your-strapi-url/uploads/small_webp_background_affisha_f0db2ea4d1.webp 200w, https://your-strapi-url/uploads/large_webp_background_affisha_f0db2ea4d1.webp 1200w"
/>
<img
data-nuxt-pic=""
src="https://your-strapi-url/uploads/large_png_background_affisha_f0db2ea4d1.png"
sizes="(max-width: 1439.9px) 200px, 1200px"
srcset="https://your-strapi-url/uploads/small_png_background_affisha_f0db2ea4d1.png 200w, https://your-strapi-url/uploads/large_png_background_affisha_f0db2ea4d1.png 1200w"
/>
</picture>
Hello!
I'm trying to using Nuxt Image with Strapi provider but
sizes
doesn't work as excepted.nuxt.configs.js
```javascript //... image: { strapi: { baseURL: "http://localhost:1337/uploads", }, } ```Because when I use this code:
the output is:
As you can see, every
srcset
value has the same url...!And here is the file data coming from Strapi:
So the excepted output should be:
But when I look into the Strapi Provider: (https://github.com/nuxt/image/blob/v1/src/runtime/providers/strapi.ts), I can't see anything about these formats...
So how can I put these
small
,medium
andlarge
urls intosrcset
?Am I missing something, or is it just not implemented?
Version
"@nuxt/image-edge": "^1.0.0-27769790.4b27db3",
"nuxt": "3.0.0-rc.11"
Thanks!