In optimizing large WordPress Websites for performance I always look at caching certain parts of the Website, mostly (of course) those that require a lot of Queries/calculation.

For the Caching of the WordPress menu I usually use a function like the one I posted as an Answer here.

This function checks if there is a transient containing the menu-HTML, and if it exists, delivers the HTML from the transient. If it does not exists, the menu is build and the transient set. To be clean, I also hook into wp_update_nav_menu to clean the transient as soon as the menu is saved, to always have the latest version available.

So far so good.

This technique works very good and gives a great performance boost, especially if the menu contains a lot of entries.

The Problem

Now, some months after developing this method, I ran into a problem, and feel stupid for not thinking about it in the first place.

Menus are different on different pages

Depending on what Page is called, wp_nav_menu delivers different HTML Code. current-menu-item and classes like that are of course applied to the menuitems.

So the problem is, what is the best way to cache the menus and still have the correct classes available for each specific page?

I thought about two versions

  • adding the classes via jQuery, which results in more calculating on the Clientside
  • caching the menus for each ID seperatly, resulting in quite some Databaseload, if the page has a lot of menuentries

However, I tend to use the second option. Do you have any concerns with caching that much HTML as Transients?

1 Answer 1


There is no generic solution for this problem: The same menu can be rendered with different walkers on different pages, or plugins change the menu on some pages.

You could extend your script to evaluate the differences to an untouched menu and build the necessary JavaScript on the fly … and cache that too … for each single page.

I don’t think it is worth the hassle. getting all the edge cases right is hard work, and the menu would still be different for users without JavaScript (search engines, unresolved script errors etc.).

  • Yep, that is exactly what I was thinking with the Javascript solution. I always cache the menus (in my new version) according to the passed $args, to have every possibility with walkers and stuff covered. It just results in a looot of different menus ;)
    – fischi
    Commented Mar 9, 2013 at 11:26
  • 1
    The code in your linked answer does not catch cases where 'wp_nav_menu_args' has been filtered to change the walker on some pages. You can use your solution in a very controlled environment only.
    – fuxia
    Commented Mar 9, 2013 at 11:30
  • @toscho Do you have an example of a good menu transient example that DOES catch the changes in the walker per page? There doesn't seem to be a good example on SE.
    – shawn
    Commented Aug 11, 2013 at 1:32
  • @shawn There is no good example. The caching mechanism cannot know which context was used by the changing script: Referer? Daylight? User-Agent? Accept-Language? Available sale items in a shop? This is impossible.
    – fuxia
    Commented Aug 11, 2013 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.