Package
next (Drupal module)
Ask the question
In my decoupled Drupal + Next.js setup, editing or deleting a redirect entity has no effect on the Next.js frontend cache. The stale redirect continues to be served to visitors even after the change is saved in Drupal.
Steps to reproduce:
- Have a Next.js frontend with
"use cache" (or ISR) enabled.
- Visit a URL that resolves via a Drupal redirect, e.g.
/old-blog redirects to /blog/my-post. The frontend caches this resolution.
- In Drupal, edit that redirect (change the source, destination, or status code) or delete it entirely.
- Visit
/old-blog on the frontend again — it still serves the old cached redirect. Drupal's revalidation signal had no effect.
Expected: The Next.js cache for the affected path is cleared after the redirect is changed or deleted, so the next visit reflects the current Drupal state.
Actual: The cache is never cleared. The Path revalidator sends ?path=/admin/config/search/redirect/edit/42 (the redirect entity's canonical URL in Drupal, which is its admin form) to Next.js instead of the frontend source path like ?path=/old-blog. Next.js has no cached entry for the admin URL, so the revalidation is a silent no-op.
Proposed resolutions:
Option 1: Patch the existing Path plugin
Add a redirect-aware branch inside Path::revalidate(). When the entity being saved is a Redirect, use $entity->getSource()['path'] instead of $event->getEntityUrl() to build the revalidation path. This keeps everything in one place but introduces a redirect module dependency into the next module's core Path plugin.
Additionally, to handle source renames (where both the old and new paths need revalidating), EntityActionEvent::createFromEntity() would need to capture $entity->original onto the event object at construction time, because by the time the revalidator runs at kernel.terminate, core has already called unset($entity->original). A new getOriginalEntity() getter on the event would expose this to any revalidator.
Option 2: Create a new dedicated Redirect revalidator plugin
Add a separate plugin (e.g. redirect_path) that handles redirect entities exclusively. It reads $entity->getSource()['path'] for the current source and uses the same getOriginalEntity() approach for the old source on rename. This keeps the existing Path plugin clean and dependency-free, and gives site builders a dedicated option to select for redirect entity types.
Please help me on deciding which approach is better.
Package
next (Drupal module)
Ask the question
In my decoupled Drupal + Next.js setup, editing or deleting a redirect entity has no effect on the Next.js frontend cache. The stale redirect continues to be served to visitors even after the change is saved in Drupal.
Steps to reproduce:
"use cache"(or ISR) enabled./old-blogredirects to/blog/my-post. The frontend caches this resolution./old-blogon the frontend again — it still serves the old cached redirect. Drupal's revalidation signal had no effect.Expected: The Next.js cache for the affected path is cleared after the redirect is changed or deleted, so the next visit reflects the current Drupal state.
Actual: The cache is never cleared. The Path revalidator sends
?path=/admin/config/search/redirect/edit/42(the redirect entity's canonical URL in Drupal, which is its admin form) to Next.js instead of the frontend source path like?path=/old-blog. Next.js has no cached entry for the admin URL, so the revalidation is a silent no-op.Proposed resolutions:
Option 1: Patch the existing Path plugin
Add a redirect-aware branch inside
Path::revalidate(). When the entity being saved is aRedirect, use$entity->getSource()['path']instead of$event->getEntityUrl()to build the revalidation path. This keeps everything in one place but introduces aredirectmodule dependency into thenextmodule's core Path plugin.Additionally, to handle source renames (where both the old and new paths need revalidating),
EntityActionEvent::createFromEntity()would need to capture$entity->originalonto the event object at construction time, because by the time the revalidator runs atkernel.terminate, core has already calledunset($entity->original). A newgetOriginalEntity()getter on the event would expose this to any revalidator.Option 2: Create a new dedicated Redirect revalidator plugin
Add a separate plugin (e.g.
redirect_path) that handles redirect entities exclusively. It reads$entity->getSource()['path']for the current source and uses the samegetOriginalEntity()approach for the old source on rename. This keeps the existing Path plugin clean and dependency-free, and gives site builders a dedicated option to select for redirect entity types.Please help me on deciding which approach is better.