So I’m finally starting to send out this “On Ruby & Computers” newsletter.
Generally, each newsletter will jump straight into a summary of a blog post of mine (about Ruby or a computing topic), where the key points and takeaways will be right here.
Also, each newsletter will feature a selection of gems I’m currently exploring, have changed the way I work, or am finding particularly useful in my toolbox at the moment. I will also add updates on some of my own gems.
To start out, the first few editions of this newsletter will cover some older blog posts of mine, and then I will move onto whatever is new.
I hope you will find these emails interesting! They should be short and infrequent. Please do reply and share some thoughts or recent writing & findings!
Thanks,
Stephen
Rails supports browser native lazy-loading for images
Read the full article here: https://www.diaconou.com/blog/rails-native-image-lazy-loading/
One sentence summary:
Rails can enable built-in browser lazy-loading on all images tags generated by Rails, with a single configuration, improving performance and saving resources.
Main Points:
Rails supports adding the browser-native lazy-loading image attribute (
loading="lazy"
) to image tags, by settingconfig.action_view.image_loading = "lazy"
.Lazy-loading loads images only when they're about to be viewed, saving bandwidth and energy. Ie an image outside of the viewport won’t be fetched until it’s within a small distance of being scrolled into view.
The default loading strategy in Rails for images is "eager" loading, not lazy, which means they are loaded when the page is fetched/parsed.
Concerns about using this feature include privacy issues, potential layout shift (ie by making Layout Shift (CLS) worse), and the effect on image "preload", impacting Time to Interactive (TTI).
The feature is not yet enabled by default in Safari due to its experimental status (as of time of writing of the blog post).
For unsupported browsers, the lazy-loading attribute is safely ignored or can be polyfilled.
The
loading="lazy"
attribute is part of the HTML specification and applies to more than just images!
Takeaways:
Enabling lazy loading can significantly reduce data usage and contribute to energy efficiency.
Be mindful of potential downsides like layout shifts and effects on page load metrics. So when implementing lazy loading app-wide, consider monitoring Cumulative Layout Shift (CLS) and Time to Interactive (TTI) metrics before and after enabling lazy loading to ensure no degradation in user experience or search ranking.
Manually specifying image dimensions can mitigate some negative effects of lazy-loaded images by preventing layout shift.
Consider browser support for the feature, especially Safari's current experimental status. For browsers that do not support native lazy-loading, a JavaScript polyfill can be used as a fallback.
This feature supports a greener web by reducing wasted energy through unnecessary image loading, please consider its usage!
Video of the network tab in Chrome showing the images loading only just before entering the viewport.
Gem Discoveries
I came across the minitest-heat
gem recently. I now use it in my client projects.
If you use minitest, check it out. The output takes some getting used to, but once you climb that hill, it is really helpful.
My Gems & Code
I’ve started adding support to vident for Stimulus outlets … still a work in progress but here is an example usage.
Imagine HelloComponent
(a ViewComponent or a Phlex component that uses vident) shows a Flash
message when its button is clicked. Here we can see how vident helps with the wiring up of the action on the button, and the connection of the outlet on the HelloComponent
host that controls the Flash
.
<%= render ::HelloComponent.new do |host| %>
<%= render ::Button.new(label: "Press me", size: :large, actions: [host.action(:reveal_briefly)]) %>
<%= render ::Flash.new(outlet_host: host) %>
<% end %>
Also, I am considering how to better manage the many gems that make up vident. The reason vident is split up is because it has many features, and thus dependencies, that users many not need. For example, if you only use ViewComponent, we don’t want to add Phlex to your dependencies. So options include:
keeping things as they are, multiple repos, multiple gems…
monorepo with multiple gems
single gem, which checks for optional dependencies using a require/rescue approach
Verdict is still out on this… if you have any thoughts, please do weigh in!