-
Notifications
You must be signed in to change notification settings - Fork 435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 👍 from me 😄 |
@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 😄 Email me: joelhawksley@github.com |
@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. |
Has there been any progress made on this in the past year? I see it's been marked for the V3 release |
@dkniffin not to my knowledge. We don't do much view caching at GitHub, so we aren't able to prioritize this work internally. We tagged this issue with the |
I'm still keeping an eye on this thread, hoping for something to get added 🤞 I wanted to mention that #980 implemented a POC of how this could work, since it's not linked in this thread. |
@joelhawksley Is there anything you can do to unblock this on the Rails side of things? You seem to have been able to guide the initial commit to Rails 6.1 that enabled ViewComponent in the first place, so maybe you have some tricks? From an outside view it seems like the PR needed at the Rails side is stalled and it is a bit unclear to me why: rails/rails#42850 |
@erikaxel I'm sorry to say that I don't think I have much sway here. Caching support for ViewComponents is likely a fairly significant effort that we (GitHub) don't currently have the resources to take on. I'm guessing @Matt-Yorkley would be keen for someone to step up and try to land that PR, for what it's worth. Perhaps you and @dkniffin could resurrect it? I'd be happy to provide pairing support as needed ❤️ |
I dropped it because there seemed to be zero interest on the Rails Core side and a strong reluctance to allow the proposed changes to some of the relevant ActionView classes that handle creating/mapping the digests for each fragment. I don't think it's feasible to do it without some of those changes. |
@joelhawksley I'm still unclear on why the Rails PR (rails/rails#42850) won't be accepted. Is there more work required to make it acceptable in Rails Core? imo, a complete re-write of the rails caching system would be great, but short of that happening, it seems like the changes @Matt-Yorkley made are a reasonable short-term solution. |
@dkniffin I don't have any context beyond what you can read on the PR 💔 I wish I had a better answer for you 😞 |
@joelhawksley Forgive me if this is slightly off-topic, but would you mind elaborating on why GitHub doesn't need view caching? How do you ensure a speedy response without the popular Russian-doll caching approach? Perhaps there are useful insights here for other View Components users to side-step this whole caching issue. |
@marckohlbrugge we cache at the request level for logged-out traffic. For logged-in traffic, we cache RPC calls vs. view rendering as view rendering is generally not a bottleneck for us but RPC calls are. Much of GitHub's UI changes based on a user's permissions so it is difficult to get a high cache hit rate. We do cache rendered markdown though, as it is more or less viewer-agnostic. It's also tricky to do view caching in combination with feature flags that modify the DOM, which we do quite a bit of. |
I think #1650 might make components and caching play well together. It would be nice to have a test that can be run against that PR, but I likely won't tackle that any time soon. If anyone is interested in writing a test for that and opening a PR, please do! |
@Matt-Yorkley would you be up for helping @BlakeWilliams validate if #1650 improves caching compatibility? |
It looks like a great PR, but I don't think it'll directly resolve the issues with fragment caching... |
Yes, #1650 definitely doesn't improve the caching problem.
still includes |
@joelhawksley I would be interested in taking this on I plan on adding a I feel this is the best way as it allows the component to control its own caching dependant on its own local state wich I feel is a better fit than caching on external global state that the component has no context on, it will also be easier to debug by just trowing a I would highly appreciate your thoughts |
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
MyComponent
is changed the cache will not be invalidated. I tried to addMyComponent
to the array used bycache
and provide aself.cache_key
method that usedActionView::Digestor
but 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
ApplicationComponent
that our components inherit from and where we overrideActionView::Component::Base.matching_views_in_source_location
so that templates are now found inapp/views/component_templates
and 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_key
probably 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::Component
provides!The text was updated successfully, but these errors were encountered: