Use more strict views url query argument caching

Created on 2 July 2018, about 7 years ago
Updated 15 July 2025, about 19 hours ago

Issue Summary

We have run into multiple issues with the cacheability of views (D7 and D8) when it comes to unique url query parameters. The most common culprit is a CRM or analytics tool that appends user-unique query parameters to links sent to users. Because pagers (as well as some other plugins) use the url.query_args cache context these requests bypass both the render and views results cache. The result is that sites can experience the worst performance during our most important promotions; this is entirely unnecessary as the query parameters aren't used by the views query at all.

As far as I can tell the only need for all non-views query parameters is in the pager links which need to preserve query arguments from the entire page request. Even when AJAX paging is used, this is necessary to support users without Javascript.

Proposed Resolution

  1. Minimally, get views results to cache to only consider the url.query_args:* cache contexts used by the view.
  2. Additionally, add an option to limit the query arguments based on the url.query_args:* cache contexts set on the view and add others back to links client-side via JavaScript. This will allow caching of the view rendered output.

1. Should result in no loss of functionality and improve database performance. This is because the rendered output explicitly adds cache contexts for url.query_args without the option in #2.

2. This will cause unexpected behavior for browsers without JS if there are query arguments unrelated to the view on the page as they will be lost. For our purposes this is an acceptable trade-off for performance, but probably means this feature would need to be opt-in until well tested.

The attached patch adds an option that filters the query parameters on the pager links to those used by the view and sets the appropriate cache contexts. The rest of the query parameters are added client-side via JS; this has a known drawback of not handling browsers running without JS enabled.

In order to cache the view appropriately other views plugins such as the filter, argument, argument_default.query_parameter plugins must be updated to only set necessary cache contexts (see related issues). These total set of url.query_args:* set in the view cache_metadata is used to determine the allowed query parameters. If the view uses cache contexts that are less specific, this filtering is abandoned.

Related Note

While investigating views caching I also discovered that pagers add a route cache context to the rendered output (but not results) simply because they pager links contain a Url::fromRoute(''). I've removed this from views_views_pre_render opting to set this client-side in JS (as it's a JS only setting anyway).

However, since pagers must render this url in the paging links this is unavoidable when a pager is used. The only alternative would be a JS-only update to the paging link, however that is a much more disruptive change than the query args change being proposed here. And only really has an impact when a view using paging is re-used on multiple routes.

πŸ“Œ Task
Status

Needs work

Version

11.0 πŸ”₯

Component

views.module

Created by

πŸ‡ΊπŸ‡ΈUnited States malcolm_p

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024