- Issue created by @cbrand02
- πΊπΈUnited States ndewhurst USA
Hi cbrand02, are you currently using the module to integrate Brandfolder images with Drupal, or are you using another means of placing Brandfolder images (with Brandfolder CDN URLs) on your site?
This module does a lot of work to avoid downloading images to the Drupal site's local filesystem so that all images are served from the Brandfolder CDN (for various reasons including governance) *but* also provide fully functional Drupal managed file entries, image fields, image toolkit, etc. so that images associated with Brandfolder-based media entities can be displayed using Drupal image styles and can do most other things that local images can do (except get served via your CDN of choice).
I'm optimistic that you'd see performance improve quite a bit by displaying Brandfolder images processed by Drupal image styles (including responsive image styles) to enforce basic resolution constraints. There are also a couple additional settings that can improve BF CDN performance depending on image type, and I'm planning to tie those into the Drupal module.
Maybe we can connect more to talk about your specific use case and needs.
Cheers,
Nathanael
Hi Nathanael,
Our site utilizes a custom theme that completely overwrites the templates for different types of content, primarily through the Paragraphs module. In order to retrieve the URL from the Brandfolder CDN to use in these templates we have a custom service with this function:
/** * Get Brandfolder image url using BF imagefactory. */ public static function getUrl($media) { $field_id = 'field_brandfolder_attachment_id'; if (!empty($media) && $media->hasField($field_id) && !$media->get($field_id)->isEmpty()) { $bf_id = $media->get($field_id)->getValue()[0]['value']; $fid = brandfolder_map_attachment_to_file($bf_id); $file = File::load($fid); $url = $file->createFileUrl(); return $url; } /* Return non-BF asset url. */ return file_create_url($media->field_media_image->entity->uri->value); }
This service is then called in preprocess hooks to pass the URLs to templates to be displayed in
img
elements. The idea is that content authors can upload images to Brandfolder and select them as media when choosing images for paragraphs. However this approach is causing some technical overhead and seems to be bypassing any sort of image optimization that may traditionally occur with this module, resulting in 1mb+ image downloads from https://cdn.bfldr.com.Would love to discuss our use case more in depth to see if there's a better way to accomplish this.
Thanks,
ChaseHi Nathanael,
Our site utilizes a custom theme that completely overwrites the templates for different types of content, primarily from the Paragraphs module. In order to retrieve the URL from the Brandfolder CDN to use in these templates we have a custom service with this function:
/** * Get Brandfolder image url using BF imagefactory. */ public static function getUrl($media) { $field_id = 'field_brandfolder_attachment_id'; if (!empty($media) && $media->hasField($field_id) && !$media->get($field_id)->isEmpty()) { $bf_id = $media->get($field_id)->getValue()[0]['value']; $fid = brandfolder_map_attachment_to_file($bf_id); $file = File::load($fid); $url = $file->createFileUrl(); return $url; } /* Return non-BF asset url. */ return file_create_url($media->field_media_image->entity->uri->value); }
This service is then called in preprocess hooks to pass the URLs to templates to be displayed in
img
elements. The idea is that content authors can upload images to Brandfolder and select them as media when choosing images for paragraphs. However this approach is causing some technical overhead and seems to be bypassing any sort of image optimization that may traditionally occur with this module, resulting in 1mb+ image downloads from https://cdn.bfldr.com.Would love to discuss our use case more in depth to see if there's a better way to accomplish this.
Thanks,
Chase- Status changed to Needs review
over 1 year ago 7:34pm 12 June 2023 - πΊπΈUnited States ndewhurst USA
Hi Chase,
Probably the simplest improvement would be to:
- Create an image style to constrain images - e.g. scale them down to the max possible output width
- Update your code to get a URL for the corresponding style derivative (see below)
// ... if ($fid = brandfolder_map_attachment_to_file($bf_id)) { $file = File::load($fid); $image_uri = $file->getFileUri(); $style = ImageStyle::load('my_constraining_style'); $url = $style->buildUrl($image_uri); } // ...
Your image style of choice could also use something like a "Focal Point Scale and Crop" effect, in which case you could set a focal point on the image field when editing the BF media entity, and that would be respected when generating the BF CDN URL in the above code.
Depending on your theming/styling scenario, you could also set up a responsive image style and use the associated picture tag/markup in your component to further optimize per screen size.
You can also append these params to the BF URL:
quality=80&auto=webp
, which will (a) compress lossy images at 80 percent and (b) deliver a webp version of the image if a given request indicates that the browser supports that.Hopefully some combination of the above will help improve things quite a bit!
Hi Nathanael,
Adding in those params to the BF URL took a >1MB image down to <200kB! Seeing similar results across the board. Thanks for the help, that was a huge win. We will implement something like your other suggestion as well.
We were also curious, what is the intention of Webhook integration if the images aren't being downloaded?
Thanks,
Chase- Status changed to Fixed
over 1 year ago 5:06pm 13 June 2023 - πΊπΈUnited States ndewhurst USA
Great! Happy to hear it, and I expect you'll see a further drop with downscaling depending on what your presentation scenarios look like.
The webhook listener allows any module to subscribe to asset create/update/delete events. The Brandfolder module itself currently subscribes to asset update events in order to fetch relevant metadata that's mapped to media properties/fields, and populate data like alt text for image fields in Drupal if there's new data in Brandfolder for that.
We might add a built-in feature whereby you can configure proactive creation of Drupal media entities when BF assets are created, which would use the webhook listener.
You can subscribe to those webhook events in order to implement custom logic, e.g. find all Drupal nodes using a recently-deleted BF asset as their hero image and replace the image with a topically relevant alternative image, notify certain Drupal users, etc. - πΊπΈUnited States ndewhurst USA
cbrand02 P.S. feel free to contact me if you want to talk more about other functionality, use cases, or some of those custom work possibilities.
- πΊπΈUnited States wesleymusgrove
Hi @ndewhurst,
Thanks for the quick response and helpful tips!
Related to @cbrand02's questions, I'm looking at this article https://medium.com/geekculture/responsive-image-optimization-with-media-... and am curious if you could provide any feedback on how the Brandfolder module could be used in conjunction with the Easy Responsive Images β module regarding defining and using a set of responsive image styles defined in Drupal?
Also if we're rendering Brandfolder images in our own custom twig templates, how do you recommend that be integrated with Twig Tweak β and the ability to specify attributes that control whether the image is lazy loaded or eagerly preloaded β¨ Add lazy loading example in Cheat Sheet Fixed , i.e. for important images that need priority for Google Core Web vitals and Largest Contentful Paint reasons?
Thanks!
Wesley Automatically closed - issue fixed for 2 weeks with no activity.
- Status changed to Fixed
over 1 year ago 9:22pm 13 July 2023 - πΊπΈUnited States ndewhurst USA
Hi Wesley,
I haven't used those modules [with Brandfolder], but here are my initial thoughts:
Re: Easy Responsive Images
It looks like the main benefits of using that module over the core Responsive Image module are:
- Auto-generation of image styles
- Twig filter if you need/want to be working in Twig templates when it comes to image rendering
- JS to choose images based on container rather than viewport width
At first glance it looks like this might work just fine with the Brandfolder module. You would create view modes for your Brandfolder-Image-Sourced media types as instructed, then, in the Twig template, just be sure to replace references to `field_media_image` with `bf_image` since that's the name of the image field on each BF media entity.
Re: Twig Tweak
If you can do this:
{# Render image using 'thumbnail' image style and "lazy" loading by attribute. #} {{ drupal_image('public://ocean.jpg', 'thumbnail', {loading: 'lazy'}) }}
Then you should be able to do this:
{# Render image using 'thumbnail' image style and "lazy" loading by attribute. #} {{ drupal_image('bf://ATEV5E6X/at/ccs81479tbnkr6gmfpbskwp/ocean.jpg', 'thumbnail', {loading: 'lazy'}) }}
(i.e. using the base URI for the Brandfolder file, and specifying any valid image style)
Let me know how you fare/fared.
-Nathanael
- πΊπΈUnited States wesleymusgrove
Hi @ndewhurst
I wanted to provide an update based on what one of my colleagues is experiencing. It seems like the `drupal_image` Twig Tweak function does not support the `bf://uri-to-bf-image` protocol and only allows images to load from `public://uri-to-sites-default-files-image`. This might be related to an existing issue where stream wrappers are needed to load any image outside of the normal `public://` directory?
See:
https://www.drupal.org/forum/support/module-development-and-code-questio... β
https://www.drupal.org/project/drupal/issues/1308152 β¨ Add stream wrappers to access extension files Needs workHowever, if we use the file id `fid` of the mirrored Drupal entity Brandfolder image reference, `drupal_image` is able to load that. In tandem with responsive images, this creates a picture tag with a bunch of responsive options for the image size.
Because of this, we are thinking we'll likely need to create some sort of twig function or preprocess hook that takes a Brandfolder asset id and turns it into an entity id.
It's either that or we try to use the Imagecache External β Twig filter function to load the absolute URLs of Brandfolder images from the CDN link.
I'm interested in your thoughts on that approach and what the pros/cons are of not using the `bf://uri-to-bf-image` protocol?
Thanks!