nuxt / image

Plug-and-play image optimization for Nuxt applications.
https://image.nuxt.com
MIT License
1.33k stars 270 forks source link

Expanded Cloudinary Features for Nuxt Image #746

Open colbyfayock opened 1 year ago

colbyfayock commented 1 year ago

We (Cloudinary) are interested in seeing how we can help support an expanded set of features for the native Nuxt Image component.

The current options when using the Cloudinary provider include some nice critical features, along with a few basic transformations:

But I'd be curious to see how we could implement a wider set of features and what that process may look like for future Cloudinary features.

Options

Manually Adding Features

We could continue contributing to the mappings and built-in URL formatter. This wouldn't include any dependencies, but would require manually mapping each of these out as needs / requests come along.

Using a Dependency

I've published a Cloudinary URL Loader with the goal of helping to provide more features in a way that could potentially be compatible with a variety of frameworks, only requiring the dependency update (ideally) for features that work off of non-Nuxt Image props (extended props).

https://github.com/colbyfayock/cloudinary-util/tree/main/packages/url-loader

This could replace some of the existing logic being used in the Cloudinary provider, though the only caveat here is implementing a breaking change or figuring out a way to customize some of the existing features that conflict. Additionally any features that exist in Nuxt Image but not yet the URL Loader could be added.

This however would add a dependency, although small, and I'm not sure if that would be okay from the project point of view and how that would technically work, so that it doesn't just get installed with anyone trying to use Next Image.

I'm also open to suggestions for this library if we end up moving forward with it.

Example of URL Loader

The URL Loader was built as an abstraction to Next Cloudinary which was trying to solve a similar goal of adding Cloudinary features on top of the Next.js Image component.

https://github.com/colbyfayock/next-cloudinary/blob/main/next-cloudinary/src/loaders/cloudinary-loader.js#L25

My hope is that we could use this same approach, where I would continue working on the core "props API" from the URL Loader side, and have new, updated, and expanded features propagate through the frameworks that use it.


Would love to hear thoughts around this! Ultimately want to see how we can work together moving forward.

I've spoken with Jakub Andrzejewski who's interested in helping out with some of this work, but I'll let him chime in on any thoughts / feedback on the above :)

Baroshem commented 1 year ago

Great idea. I will add my two cents here in a few days 🙂

Baroshem commented 1 year ago

@pi0

What is your opinion on that feature?

mayashavin commented 1 year ago

Hi @colbyfayock,

First of all, the proposal sounds great.

However, as the initial contributor of the code for cloudinary provider (yes I was :)), the decision not to use any additional library such as the url generator like cloudinary-build-url when implementing this file was based the following reasons:

  1. The Nuxt Image should be as generic as possible, and users are not necessary using Cloudinary when they installing the module, and having them install the url generator for Cloudinary specific as dependency seems not the right approach to me, regardless the size. However, if the team thinks it's ok, and maybe it's time to do so. @pi0 @danielroe What do you think?
  2. There is a Cloudinary module for Nuxt, with extended capabilities. That module was meant for using in advanced use case, while the Nuxt image solely aims for optimizing images on the most common scenarios and covering the essential usage of any providers, including Cloudinary.

Also, if I remember correctly, the Nuxt image component with Cloudinary provider has the mechanism to add any custom transformations (modifiers) besides those defined inside the default modifiers.

I would suggest to review the component's modifiers, and maybe manually add the crucial modifier and leave the option to extend it to the users, instead of trying to include every transformations possible offered by Cloudinary. Otherwise, once you include Cloudinary url generator as the dependency, other provider can request for the same applied to them.

Disclaimer: I have been away from this project for some time, so maybe some of my assumptions are no longer relevant. Feel free to correct me :)

colbyfayock commented 1 year ago

We'll (Cloudinary) surely defer to the Nuxt preference. The idea behind using the loader that I linked is that by updating the dependency new features would "just work" as things get added, but that doesnt necessarily need to be in the core module.

I'd argue that there should be a design decision from Nuxt as to what the Nuxt/Image module should support cross-provider, whether that's a simple set or if it's whatever the provider wants. If the latter, it may make sense to implement that loader as long as the dependency only gets installed when using the cloudinary provider (not sure how opt-in works in this regard for Nuxt)

Baroshem commented 1 year ago

@pi0

What are your thoughts on that? Maybe in this case it would be better to revive the @nuxtjs/cloudinary module?

I could work on migrating the module and adding this new functionality :)

pi0 commented 1 year ago

Sorry for late response.

Checking @cloudinary-util/url-loader, it is zero dependency so no objections to use it for cloudnary preset and generating URLs (same for other presets as long as remains zero dep)

I think in general reviving @nuxtjs/cloudinary would be the best to add extra functionalities. Specially because some of them are not image only and some improvements and unique features like upload-on-build can be introduced there but not here.

Baroshem commented 1 year ago

@colbyfayock

We have talked about this feature with Pooya and we think that it can be added as an addition to this module. For more advanced cases, we could revive nuxt cloudinary module but this would require much more work.

I will take a look at the current Cloudinary Image interface and try to add the support for the url-loader of yours next week.

Will keep you posted about the results :)

colbyfayock commented 1 year ago

thanks everyone

just an FYI one potential option is to still use the url-loader for both instances in the event that it makes maintaining the logic easier

something to consider for all providers is whether or not to have a fixed amount of features that external providers can have? or something along those lines, not sure what that would look like, but a guide to where that line is, even if that is reduced features for the built-in (less core maintenance id think)

@Baroshem let me know if you wanted to meet up again to chat through any of this! i do like that we'll then be able to continue development of the other features like @pi0 mentioned like the Upload stuff which is very handy

maybe we can think through what the scope of the entire package looks like to make sure it's a cohesive experience for Nuxt users

Baroshem commented 1 year ago

Hey guys,

I just had a quite successful call with @colbyfayock where we have talked about potential implementation ideas on having more advanced transformation options for Cloudinary. Here is a short summary:

Useful links for reference:

pi0 commented 1 year ago

Thanks for the updates @Baroshem ❤️

Just to be clear, i think migrating to @cloudinary-util/url-loader from image module is a good idea. Also for platform-only advanced transformations, image module allow that (we document them in provider page like this)

Baroshem commented 1 year ago

If so, lets then stick to the current Image module and cloudinary util url loader. I will work on this in the upcoming days.

Thanks for the fast reply @pi0 !

CC @colbyfayock :)

Baroshem commented 1 year ago

@pi0

I have a question about implementing new advanced transformations for Cloudinary. I have two approaches here:

  1. Add a new object property to modifiers called for example options and these all options will be send to the Cloudinary util that will be added with this feature. Non breaking behavior of just adding a new property but it will basically make every other modifier not usable as cloudinary util has all modifiers currently supported by the Nuxt Image (AFAIK).
  2. Pass all modifiers as options to the cloudinary util with backward compatibility by creating a mapper so that cases like modifiers.effect: 'grayscale' will be transformermed into grayscale: true.

Which one do you think is better?

colbyfayock commented 1 year ago

Option 2 has a better DX. Devs shouldn't necessarily have to care or think about the example in option 1. It's also confusing.

Baroshem commented 1 year ago

I agree with that. Thanks for feedback @colbyfayock :)

It is much better approach. The first one will mean that eventually we would need to to the same decision but later on.

What about this backward compatibility for the current features of cloudinary provider?

I can do a mapping of all currently available options to the cloudinary-util/url-loader interface so that current users and future ones will have the same behavior. Do you think that it is necessary? Or should we skip it and just implement the new approach and just document it correctly in the docs?

@pi0

colbyfayock commented 1 year ago

the easier method would be to use the same options in the loader but that would certainly be breaking

i defer to what you and @pi0 think about that one

vanling commented 5 months ago

Would it be possible to add chained transformations? https://github.com/nuxt/image/issues/913

for example to generate: https://res.cloudinary.com/xxxx/image/upload/e_trim:10/c_pad,g_south,h_260,w_70/c_limit,h_260,w_70/b_rgb:fff,f_auto,q_100/cld-sample.jpg

'grouping' the modifiers

:modifiers="[
              { e: 'trim:10', c: 'pad', g: 'south', h: 260, w: 70 },
              { c: 'limit', h: 260, w: 70 },
              { b: 'rgb:fff', f: 'auto', q: 100 },
            ]"
colbyfayock commented 5 months ago

hey @vanling there's 2 ways you can chain transformations right now, though it might not be exactly what you want

the effects prop supports an array, but only a limited set of options that you can pass in, and not sizing

the rawTransformations prop supports the URL style parameters passed in as an array

https://cloudinary.nuxtjs.org/components/cldimage/configuration

vanling commented 5 months ago

@colbyfayock Thanks, i missed that 'rawTransformations' option on that module. Will give it a try !