cms icon indicating copy to clipboard operation
cms copied to clipboard

nocache: Always fallback to partial - no placeholder text

Open stuartcusackie opened this issue 1 year ago • 5 comments

Bug description

I think the @nocache directive / tag should be updated to output the partial when the statamic.web middleware is not applied, if possible. Let me explain my reasons:

I have a custom auth system and guard from my front-end. The site header contains a menu that differs based on your authentication status. For this reason I am applying @nocache to the partial.

header.blade.php

<div>
  ...
  @nocache('partials.nav-main')
</div>

partials/nav-main.blade.php

<div>
	@foreach(main_nav() as $item)
		<a href="{{ $item['url'] }}">{{ $item['title'] }}</a>
	@endforeach

	@guest
		<a href="{{ route('login') }}">{{ __('Sign In') }}</a>
		<a href="{{ route('register') }}">{{ __('Join') }}</a>
	@else
		<a href="{{ route('settings') }}">{{ __('Settings') }}</a>
	@endif
</div>

The problem:

If I don't add the statamic.web middleware to my auth routes (which contain this header partial) then I will see NO_CACHE_PLACEHOLDER.

If I do add the statamic.web middleware to my auth routes then the @nocache tag works, but then I have to add a lot of auth routes (login, register, password reset, etc.) to the static cache invalidation exclusions. This feels unnecessarily complicated.

Solution:

Just output the partial (as would happen using include()) when static caching is not enabled or not available (no statamic.web middleware) is on the current route.

Thanks!

How to reproduce

Use @nocache directive / tag on custom auth routes.

Logs

No response

Environment

Laravel Version: 9.30.0
PHP Version: 8.1.1
Version: 3.3.36 PRO

Installation

Fresh statamic/statamic site via CLI

Antlers Parser

No response

Additional details

No response

stuartcusackie avatar Sep 19 '22 10:09 stuartcusackie

but then I have to add these routes to the static cache invalidation exclusions.

You shouldn't have to do that. That's what the nocache is for, to work WITH static caching.

edalzell avatar Sep 19 '22 15:09 edalzell

You shouldn't have to do that. That's what the nocache is for, to work WITH static caching.

I understand that but there is a problem with this concept when using custom routes - especially ones with forms and authentication logic. As explained, I have a header partial that is used in custom authentication pages (login, reset password, dashboard etc.). This same header is also used in my Statamic pages, on which static caching is applied.

So I have two bad choices in my case:

  1. Make two copies of the same header partial. One for my custom auth pages and one for my statamic pages. This is not a good solution in my opinion as I'll end up with two versions of the same partial to manage. I will likely need two separate layouts as well.
  2. Apply the caching middleware to my auth routes and then ignore them in the static cache invalidation. Again, this seems unnecessarily complicated.

What I am suggesting is that the nocache tag simply falls back to the partial when the caching middleware is not applied, instead of outputting the "NO_CACHE_PLACEHOLDER" text, which I don't think anyone would want to see.

stuartcusackie avatar Sep 19 '22 17:09 stuartcusackie

What I am suggesting is that the nocache tag simply falls back to the partial when the caching middleware is not applied, instead of outputting the "NO_CACHE_PLACEHOLDER" text

The challenge is that by the time the tag is run it's too late, and it doesn't know about the middleware. And the placeholder has to be there, in order to make the whole thing work.

Interesting problem.

edalzell avatar Sep 19 '22 17:09 edalzell

Hmm yes, I have probably underestimated the complexity of this one. I have no idea how nocache works. Perhaps the sequence can be changed so that it is aware of the middleware.

Adding the statamic.web middleware to all routes works fine. It just seems wrong to add it to pages where I don't want any static caching at all (e.g. login, register).

Maybe I could temporarily workaround with something like this:

@if(in_array('statamic.web', Route::current()->gatherMiddleware())
   @nocache('partials.nav-main')
@else
  @include('partials.nav-main')
@endif

stuartcusackie avatar Sep 19 '22 21:09 stuartcusackie

You can always go the other way if you want, don't use static caching but do use the cache tag.

edalzell avatar Sep 19 '22 22:09 edalzell

Didn't see this issue when creating #7820, sorry. Maybe possible fix in the comments and example repo.

jhhazelaar avatar Apr 03 '23 19:04 jhhazelaar