Components should play nicely with Rails caching mechanisms #234
Comments
|
Happy to see another report on caching! Issue 42 also opened up this question in the early days and is marked with the V3 tag. I'll start doing some research on my end based on your research @ozzyaaron and try to see if I can take a stab at it 🤘🏽 @joelhawksley , anything I'd need to do or know before starting? All help is welcome! |
|
@pinzonjulian I don't know if there's much I can add here, as my experience with caching is fairly minimal. Anything we can do to improve our compatibility with Rails gets a big |
|
@pinzonjulian Not sure if you're still researching this, but I was interested and did some digging on my own. Here's what I found:
So, in summary, I think there's two things we'd need to change to get caching working for ViewComponent:
I'm not sure how much of that I misunderstood, but hopefully it helps! @joelhawksley perhaps you know of someone at Github with more experience in this area that could spend some time looking over this and make a recommendation? I'd be happy to make a PR to ViewComponent and/or Rails, but I want to make sure I'm on the right track before I dive in over my head. |
|
Hey @dkniffin ! I've been working on and off on this and I've been documenting my progress here: https://www.notion.so/View-Component-07d8bef1ed3342498b5805cc3166a82a It's a little messy because I wasn't planning on sharing those but I've had very little time lately to put more time into it. Take a look at the section that says "The whole journey" for a breakdown of all the path Rails takes to cache something. I've loved digging into this but it's been pretty rough without any guidance so I'm glad you're chiming in! I'd like to bring my findings into Github somehow so we can build upon it together but not sure how. Any ideas @joelhawksley ? |
|
@pinzonjulian that's awesome! We both followed through it all and came to nearly the same conclusion. The bit that I think you missed was the part where Digestor.digest builds up a dependency tree. I think the |
|
Yeah I definitely remember the dependency tree being built but that's where I started slipping a little. I couldn't understand how to register a new location for Rails to look for dependencies. I'm curious to see if fixing that would unblock all of the possible ways for caching (there's a comprehensive list in my notion page). I'd really like to help and keep learning about this so count me in in any further development if possible! |
|
@dkniffin @pinzonjulian thank you for all of the time you've spent researching this issue! Perhaps one of you could provide a PR with a failing test for us to work against? I'd love to set up some time to pair on a solution. |
|
@joelhawksley I would be glad to do that, but I'm not quite sure how that test would look. This is the template I'd want to test:
and the result I'd be testing for is that if the code for Edit: I found this test in the rails codebase that's kinda similar, but again, what I'd need to do is test that a change to the component invalidates the cache. I think that test I linked is a little different. |
|
@jhawthorn I hope you'll forgive me for summoning you to a random repo you haven't contributed to before, but I saw you made a somewhat recent change to My team and I would really like to use this library, but I'm afraid that this lack of caching support may be a blocker for us |
|
@joelhawksley Any progress on this? |
|
@dkniffin I haven't had the time, sadly. Would you be willing to write a PR with a failing test? Perhaps we could pair together on it |
|
@joelhawksley I definitely empathize :/ I haven't had much time to dedicate to this either. I would love to create a PR with a failing test, but I honestly don't know what that failing test would look like. I can't wrap my head around a proper way to test that changing the contents of a file busts the Rails cache, unless I use However, a team member and I have thought a little about how this feature could be implemented. As stated above, I think there's two things that need to change:
I hope to find some time at some point to test the idea in 2 out. I think that would make more sense as a PR to Rails, but I'm not sure how to have that regex not be dependent upon how ViewComponent classes are named. Maybe I could make it generically "look for any instances of a |
|
@dkniffin we have tests that change files, see https://github.com/github/view_component/blob/master/test/view_component/integration_test.rb#L48 for an example. Perhaps you could build off that? |
|
@joelhawksley Oh, awesome! I didn't know there was something like that in the codebase already. Yes, that should make writing that test a bit easier. I'll see if I can take a stab at it sometime this week. |
|
@joelhawksley Alright, I've created that PR: #476 Now for the solution. I don't think there's a way to accomplish #2 above without some changes to Rails, specifically in ERBTracker. I have a rough idea of what needs to change there, so I'll take a stab at it. Hopefully the Rails team is receptive to the change. Edit: I dug into the code with a debugger a bit and tried to trace what was going on, but had some difficulties. For some reason, in that ERBTracker, I was receiving a subset of the code I thought I would, and it didn't even include the render line for my component class. Perhaps I need to solve # 1 above first, idk. I'll see if I can dig in again some more tomorrow. |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
|
Bump |
|
@joelhawksley A few of my teammates suggested a possible "workaround" to the problem here. We could add a new For example:
It's still not perfect because users will have to remember to do that, and if there's a cache call at the top of many layers of abstraction, it would have to be aware of the component call deep below to include it, but it's a start. What do you think? |
|
I'm pretty sure I think it would be nicer if ViewComponent tracked with the Rails configuration including things like prepended view paths and whether classes are being cached or not. Further what we're seeing in the latest release (2.20.0) the way templates are found is becoming harder to interact with (we used to override I think it would be great if in the short term the class itself (derived from |
Agreed. We've already moved in that direction with #509.
I'd be 👍🏻 to this change, and have started work on implementing
I'm sad that this was necessary for you, and hope we can improve ViewComponent so it no longer is |
|
Hi @joelhawksley thanks for the questions! We're getting a lot out of using ViewComponent thus far and its free, so please don't take my opinions negatively, we're thankful for what we get
Thanks! IMO a great move :) I have to do a bit more testing but I think when I was looking at 2.20.0 the issue I saw was that EDIT: upgrading to 2.21.0 didn't fix it for us. I'll probably be able to take more of a look at it tomorrow but it doesn't appear to call the component class's On the ability to have a method This is just my opinion based on our use so far. I personally think there are 2 concerns
I think you could probably get away with just allowing people to define both together (e.g. The reason I separately suggest a template filename is for the concern of users and formats/variants. As a user I'd far prefer to just deal with a template name (perhaps as simple as a For most users I'd imagine they'd never notice and not have to change anything with changes like the above as
Hey man, don't worry! We used a couple component frameworks previously and they all had major flaws even for our meager use cases. ViewComponent is one we have jumped into feet first though and have only had to override 1 method thus far. I'd love to be able to help out but have a couple other outside-work projects I'm already helping on. I do think if ViewComponent were able to get the template path exposed and then add an effective watcher to the Rails cache digestor mechanism it would sort out most of our current concerns. Even with the small issues, ViewComponent is making our code easier and more robust for sure! Thanks to all the contributors! |
|
@ozzyaaron thanks for your detailed feedback! Can you provide more context on why you're choosing to locate templates in a separate directory from the component objects? If it's just for the sake of caching, I feel like we should pursue supporting caching properly with the existing template organization structure. FWIW, we did have a version of ViewComponent a while back that used templates from |
|
@joelhawksley you're absolutely right that we have just chosen to change the location and template prefix to work with Rails caching. I think if we were able to have ViewComponent support caching normally through calls like In some places I've been there were some use cases for sharing templates outside of the Rails or server-side framework. With a pretty small bridge/adaptor we've rendered template via multiple mechanisms. For example writing templates that would be rendered by Node and Ruby systems - especially when distributing to multiple targets like mobile, desktop and the web. I'm not suggesting that as a use case for ViewComponent just as an interesting outcome I've seen really investing in component templates previously. |

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.

Feature request
Components should provide a digest to Rails views, or be able to use Rails explicit caching directive comments or be able to provide a cache_key.
Essentially we should be able to invalidate a cache based on whether the Component class or template has changed.
Motivation
I'm just building on some previous reports primarily around where templates live and the filenames of the template/s. My concerns come down to integrating with Rails caching basics.
The issue that we run into is basically summed up by
In this case if the template for
MyComponentis changed the cache will not be invalidated. I tried to addMyComponentto the array used bycacheand provide aself.cache_keymethod that usedActionView::Digestorbut without having some further mechanism to invalidate the digestor's cache for the template/s when the template changes this didn't work.Rails allows for explicit directives to be used (https://guides.rubyonrails.org/caching_with_rails.html#explicit-dependencies) but by default this will only look inside
app/views. You can add a view pathappend_view_path("app/components")but the digestor is expecting a partial and so a template filename would have to be prefixed with underscore.The way we are currently working around this is to have an
ApplicationComponentthat our components inherit from and where we overrideActionView::Component::Base.matching_views_in_source_locationso that templates are now found inapp/views/component_templatesand where the files are prefixed with underscore.Then in the above example where cache invalidation does not work via template digest changes we can do
I think if AV::C is going to be core or integrate with Rails it would need a way to expose template digests nicely, or provide
cache_keyprobably at the class level. If not then as a last resort we would need a way to use explicit directives in templates that use ActionView::Components internally.I'd also be all👂 to people who have solved this already or if I've missed something about the features
ActionView::Componentprovides!The text was updated successfully, but these errors were encountered: