Skip to content
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

Exclude sections from static caching (nocache tag) #6231

Merged
merged 71 commits into from
Jul 13, 2022
Merged

Conversation

jasonvarga
Copy link
Member

@jasonvarga jasonvarga commented Jun 20, 2022

Another evolution. This is heavily inspired by #5575, thanks @JohnathonKoster.

This allows half or full measure caching to be enabled, and you can use a nocache tag pair to surround chunks of your template that you want to be dynamic.

<{{ now }}>
{{ nocache }}<{{ now }}>{{ /nocache }}
<date when the page was cached>
<current date>

Replacers

The key feature of this PR is the new concept of "replacers", inspired by https://github.com/spatie/laravel-responsecache.
This lets a class replace bits of a response.

For example, if you have a {{ csrf_field }} in your template, the class will find any instances of the token, and replace it with some string like <csrf-token-placeholder>. Then on subsequent requests, it will replace it with the user's actual one.

// rendered template
<input type="hidden" name="csrf_token" value="initial-users-csrf-token" />
// cached response content
<input type="hidden" name="csrf_token" value="<csrf-token-placeholder>" />
// another user's request, processed by the replacer
<input type="hidden" name="csrf_token" value="another-users-csrf-token" />

The CSRF token replacer is enabled by default. You don't need to use nocache tags. It'll just work.

The only difference between our replacers and the Spatie version is that ours can modify the initial response in addition to the one that gets cached.

The nocache tag

Whenever a nocache tag is used, the contents of that tag pair as well as the contextual data are stored and replaced with a placeholder string.

The "cascading" data is stripped out from the initial request, and then on subsequent requests, fresh cascade data is merged back in.

The nocache Blade directive

In Blade, we have no way to "capture" some tag pair contents. So instead of using a tag pair, you'd extract the bits you want to keep uncached into a dedicated view. Then you can use the @nocache directive, passing in the view name.

@nocache('dynamicstuff')

Full measure support

Using this feature with full measure caching will require javascript to be enabled.
A little snippet will be injected into the page, and will perform an ajax call to get the no-cached bits. There will be a slight delay or "flash of unstyled content" while the request is happening. You can customize what's there in the meantime, for example an svg loading animation.

Differences from #5575

  • It uses the actual Laravel cache instead of just files in the cache directory. If you use Redis, it'll go in there. Running artisan cache:clear will actually clear it, regardless of the cache driver.
  • Using nocache tags no longer bypasses the configured static caching driver.
  • It's decoupled even further from Antlers. Instead of using a {{ nocache:evaluate region="abc" }} tag and allowing the parser to replace it, this PR uses the replacer feature.
  • It fixes an issue where the "page entry" wouldn't be replaced. This PR makes sure to re-inject the entry belonging to that url back into the cascade.

Todo

  • Rename no_cache tag to nocache. It's way easier to type.
  • Invalidation seems unnecessary at the moment
  • Blade support , maybe.
  • Use full absolute URLs instead of just URIs
  • Nested nocache, and/or inside cache tags
  • Fix template view data disappearing
  • Usage in loops
  • Either fix or document as a caveat that the csrf token doesn't automatically get replaced when using full measure.
  • Find a way to avoid needing to exclude /!/nocache from csrf verification manually

@jonassiewertsen
Copy link
Contributor

Do I read the code right, that it does support full measure caching as well?

The description is only saying half, but I do see some JS magic in there to make it happen anyway :-)

@jasonvarga
Copy link
Member Author

jasonvarga commented Jul 8, 2022

Yes it supports full measure now. I thought I had updated the description, but I guess I only mentioned it in the docs.

@jasonvarga jasonvarga merged commit e2176bd into 3.3 Jul 13, 2022
@jasonvarga jasonvarga deleted the feature/nocache branch March 2, 2023 00:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants