Problem/Motivation
#2381277: Make Views use render caching and remove Views' own "output caching" replaces output caching with render caching.
Render caching though is disabled on POST requests, so that ajax requests aren't cacheable.
We need to get #956186: Allow AJAX to use GET requests in, to be able to get render caching done.
Proposed resolution
- Add setting for query type to views pagers
- Make views pager respect that setting so that it uses the correct protocol
- Get render caching to work on views AJAX paging responses
Remaining tasks
- Fix broken tests on 8.3 re-roll.
- Get #956186: Allow AJAX to use GET requests committed
- Verify that we have enough test coverage on this issue
- QA testing to get to RBTC
User interface changes
I added a "pager query type" selector to sql-base pagers which becomes active if you set the view to use AJAX.
API changes
- Added a "getParam" method to ViewAjaxController to make it easier to get parameters off of a request.
How to test
- Install a new site
- Apply most recent patch from this issue (currently: https://www.drupal.org/files/issues/2500313--views-get-paging-support-83...)
- Apply https://www.drupal.org/files/issues/ajax-956186-65_2x_1.patch from #956186: Allow AJAX to use GET requests
- Create at least five articles
- Create two views as follows
View 1
- Add a block display
- Call it "GET pager view"
- List all nodes
- Turn on AJAX for the view
- Use a pager (try them all if you can); 2 per page, set query type to GET
View 2
Same as View 1, except:
- Call it "POST pager view"
- Set query type on the pager settings to POST
Now:
- Place both blocks somewhere on the page
- Start using the pager, and use the network tab (helpful to filter by XHR) to ensure that the views are using the correct protocol for their requests.
Some other things to try:
- Using a table display, ensure that column sorting is respected after paging back and forth.
- Add an exposed filter and make sure paging works after the setting the filter value.
- Test the render caching somehow. Make sure page cache is turned on, and put a breakpoint or something inside a function that runs when rendering a row. The breakpoint should hit a) when the cache is first populated and b) if something invalidates the cache (i.e. that node is updated).
| Comment | File | Size | Author |
|---|---|---|---|
| #92 | 2500313-92.patch | 15.18 KB | _utsavsharma |
| #92 | interdiff_91-92.txt | 830 bytes | _utsavsharma |
| #91 | views-render_caching_ajax_requests-2500313-89.patch | 15.19 KB | michelle |
| #87 | 2500313-87.patch | 15.13 KB | supreetam09 |
| #85 | 2500313-85.patch | 15.27 KB | supreetam09 |
Comments
Comment #1
wim leersComment #2
wim leersComment #3
mgiffordComment #5
dpolant commentedI have a first pass at this ready. It depends on the patch from https://www.drupal.org/node/956186#comment-11498819.
Here's what I did:
1) Made a SqlBase pager setting that lets you choose GET or POST.
2) Fixed ViewAjaxController so that it gets query parameters in a way that respects request method.
3) Changed the way that it renders the view so that render caching works.
Let me know what you think. This should work on 8.1 stable if you get the 8.1.8 version of the patch from that other core issue.
Comment #7
dpolant commentedI'm going to need to look at some of those tests. We probably need to wait until https://www.drupal.org/node/956186 is committed to get past some of the AJAX paging related ones, but here is a diff that should fix the schema errors.
Comment #9
dpolant commentedI'm very interested in getting these tests to pass. Can anyone point me in the right direction for how to move forward with this?
I've gotten to the point where it's failing because the $view->display_handler is empty in ViewAjaxController::ajaxView. I'm thinking this has something to do with the mock view not being built correctly under the new conditions.
Anyone have a guess about this, or some advice?
Comment #10
dpolant commentedActually I figured it out. I needed to a) set the query params in a different way for GET and b) set up a mock expectation for buildRenderable instead of preview. It will take a bit more legwork but I should have these tests passing soon ...
Comment #11
dpolant commentedAll tests should be green now. I added separate tests for paging via post vs. via get.
Comment #12
dawehnerNice work @dpolant!
Comment #13
dawehnerI'm a bit confused how this patch is related to the title of this issue. You seemed to have done something different :)
Comment #14
dpolant commentedYou're right. Here's a summary of what I did:
1) Added render caching to ajax views
2) Added support for GET requests for ajax views
3) Added tests
Comment #15
dawehnerI think this title is more fair then :)
Comment #17
damienmckennaHow testable is this with our current testing suite? Could one of the VDC maintainers please chime in to clarify what sort of tests they would like to see? Thanks.
Comment #18
dawehnerWell, similar to the way how we test REST requests we could also tests those views ajax requests. Sending the right response and ensure the right headers are send.
Comment #19
shrop commented@dpolant: Do you have any manual testing instructions?
Comment #21
dpolant commentedRe-rolled against 8.3x
Comment #23
dpolant commentedComment #24
dpolant commentedFixed JS coding standards error.
Comment #25
dpolant commentedComment #26
dpolant commentedComment #27
dpolant commentedComment #28
dpolant commentedDo we need more tests for this? See Drupal\Tests\views\Unit\Controller\testAjaxViewWithPager - this will now test the page endpoint as a GET request and it is pass.
Comment #29
dpolant commentedComment #30
dpolant commentedComment #31
dpolant commentedComment #33
edurenye commentedRerolled.
Comment #35
petermallett commentedThere's already a patch for 8.4.x, but I still needed one for 8.3.x as of 8.3.7 & figured someone else might, as well; so here's the patch from #24 re-rolled for 8.3.7.
Comment #36
nikunjkotechaI used the patch and still was not able to see the headers properly set, I then checked the module ajax_cached_get but no luck, I than checked the differences in use of CacheableResponseTrait and it seemed that all the conditions were failing as response object was not instance of CacheableResponseInterface.
Updated the patch, now ViewAjaxResponse implements CacheableResponseInterface and CacheableResponseTrait was already used. Confirmed for my case the headers are properly set now.
Patch is only for 8.3.x as of now and once I confirm it on Acquia cloud I will work on 8.4.x
Comment #37
nikunjkotechaAnd now I've run into real issues, ViewExecutable->unserialize requires \Drupal::request() which is null as Drupal is trying to render from cache
Bottom line - don't use my patch till further notice.
Comment #38
nikunjkotechaComment #39
merauluka commentedAfter updating to 8.4.2, the patch from 33 no longer appears to apply cleanly due to a small code change in core. This is a reroll of 33 against 8.4.2.
Comment #42
merauluka commentedHere is a new re-roll of the patch for 8.5.x.
Comment #44
merauluka commentedAnd I made the patch against the wrong directory. Attaching a new patch and trying against with automated testing.
Comment #46
wim leersThanks for pushing this forward again, @merauluka! 👌 Hopefully Views maintainers can soon review this :)
Comment #47
dawehnerI'm a bit confused about this one. Why do we have a pager specific method even there are other places where one could do ajax requests with views, like exposed filters.
Comment #49
piyuesh23 commentedWe have been using this patch on a Project since past few Drupal 8 releases & while upgrading to 8.7, it failed to apply. Re-rolled this patch for 8.7.x. Attaching patch file here.
Comment #50
finne+ for #47:
I would love to use cached views ajax reloads on a facets filter or exposed filter. What was the reason to only do this for paging?
Comment #51
malcolm_p commentedI also feel that #47 is an important consideration. Getting exposed filters using GET for Ajax is critical for performance.
Comment #52
hkirsman commented+1 for this getting this on exposed filters!
Comment #54
pdenooijer commentedApplied the patch from #49 with 3 way merge and update the code a bit:
Comment #56
luksakI tested this on 8.8.5 with the latest patch and the patch mentioned in the IS from #956186: Allow AJAX to use GET requests. The first uncached ajax request works, but the next cached request throws this error:
Error: Call to a member function get() on null in Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers() (line 860 of /web/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php)Comment #57
pdenooijer commented@Lukas von Blarer, I had the same error. Currently working on a new patch that will fix this issue. Serializing the view is the problem, if that is not serialized the caching will work as expected.
Comment #58
pdenooijer commentedUpdated previous patch to solve the serialization problem when caching the response.
Tests still need work, I think they should be extended to test both GET & POST requests.
Comment #59
pdenooijer commentedThe serialisation of the ViewExecutable is quite broken, so for now just don't cache it.
Updated to be inline with the other patch in the mentioned issue.
Comment #61
olivier.br commentedpatch rerol for drupal 9.0
Comment #62
olivier.br commentedIt works for pager but not for exposed filters.
I agree with #50, seems weird to have caching enabled when using pagination but not when using an exposed filter.
Here is a new patch that use the setting in pagination also for exposed filters. Maybe this request type setting should be in the display settings and not in the pagination settings.
Comment #63
arunthampiklm commentedThis patch will fix the issue on exposed filter in 8.x
Comment #64
avpadernoComment #67
mr.york commentedReroll #62 patch and try fix tests.
Comment #68
mr.york commentedFixed typo in patch.
Comment #69
avpadernoComment #70
anmolgoyal74 commentedRe-rolled for 8.9.x
and fixed CS issues in 9.2.x
Comment #72
mr.york commentedAdd missing JS code.
Comment #73
avpadernoComment #74
mr.york commentedFixed JS codes.
Comment #75
mr.york commentedReroll.
Comment #76
huzookaJS coding standard.
Comment #77
huzookaComment #78
huzookaComment #80
mr.york commentedChange media test.
Comment #82
melvinlouwerse commentedreroll
Comment #83
avpadernoComment #85
supreetam09 commentedRerolling..
Can't seem to generate the interdiff as its throwing error
interdiff: Whitespace damage detected in inputComment #86
avpadernoComment #87
supreetam09 commentedAdding new patch for custom commands failure.
Comment #89
uber_denis commentedI just ported the code of #87 to make it work with 9.5.x branch.
Comment #90
_utsavsharma commentedFixed CCF for #89.
Comment #91
michelleI've re-rolled this to work with 9.5.1. It wasn't applying due to changes from "will()" to "willReturn()". I fixed the conflicts manually. I have not yet tested the patch aside from seeing that it applies.
I'm going to keep this at needs work because core patches should be going against D10, now, but the client needs it for D9 so that's what I did. If I can, I'll see if I can circle back and get it to D10.
Comment #92
_utsavsharma commentedFixed CCF for #91.
Comment #93
avpadernoComment #94
avpaderno(I apologize: The status change was wrong.)
Comment #95
catchPostponing on #956186: Allow AJAX to use GET requests.
Comment #96
wim leersUnblocked!
Comment #97
catchI think we actually don't need to do this any more - #956186: Allow AJAX to use GET requests already converted Views (without configuration) since it was the main (only) use-case for non-form AJAX in core, so Views is using GET for pagers etc. in Drupal 10.1 already.
Comment #98
wim leersIt's using
GETAJAX requests indeed, but the scope of this issue seems to also stress the need to add render caching in that situation. But perhaps that's already happening? 😄(I could investigate/verify that too but it's been ages since I've looked at Views' render pipeline, it'd probably take you only a few dozen seconds to check? 🤓😅)
If that's already happening too, then I definitely agree this can be closed (as a duplicate?).
Comment #99
catchViews render caching is just normal render caching now, that's why this issue was opened in the first place!
Drupal 7: Views has its own HTML caching pipeline, which works on POST requests, but doesn't handle any of the things Drupal 8+ render caching does like cache tags etc.
Drupal 8+: Views uses core render caching, which is great for normal GET requests, but skips caching on POST requests.
Drupal 10.1: cache cache cache cache cache cache!
Closing as outdated.