For a while I've been having difficulty handling large navigation in craft. I built this site a while ago, and if I am honest I would probably change the structure if I was doing it again, but that's for another time.
The nav is stored in a structure and each navigation entry is either linked to an entry or a custom url is entered. There are approximately 300 pages in the entire nav.
Here is the code I use to generate the nav:
{% macro navigation(pages, id='') %}
<nav role="navigation">
<ul role="menu" {% if id|length %} id="{{ id }}" {% endif %}>
{% nav node in pages %}
{% set url = node.url|length ? node.url : node.linkedEntry|length ? node.linkedEntry.first().url : node.customUrl %}
{% set active = node.slug == craft.request.getSegment(node.level) %}
{% set class = node.children|length ? "has-children" %}
{% set class = active ? class ~ " active" : url == craft.request.url ? class ~ " active" : class %}
{% set separator = node.separator ? 'separator' %}
<li class="{{ class is not empty ? class : "" }}{{ separator }} level-{{ node.level }}" >
<a href="{{ url }}">
<span>{{ node.title }}</span>
</a>
{% ifchildren %}
<ul class="children">
{% children %}
</ul>
{% endifchildren %}
</li>
{% endnav %}
</ul>
</nav>
{% endmacro %}
The problem I have is that this is incredibly slow, in some cases I see load times of over 10s, which is unacceptable! I know that this is caused by the nav and not the rest of the page content.
I use caching to speed rendering up, and this works fine, but that only really masks the problem.
I reckon that the bulk of the time is taken up checking whether it is active, what class it has etc. Is it possible to store it as a blob and run some kind of regex match on it as a whole?
I'd prefer it if the user could change the nav through the CMS, but if I am honest, this is not a necessity. I've even thought about hardcoding it!
Any one have any pointers or experience in the past?