Делал сайт с верхним меню (js, выпадающее, содержит все страницы сайта) и боковым меню (отображает продукцию). Всего около 400 страниц с 6 уровнями иерархии.
Столкнулся с такой проблемой - даже со включенным кэшированием, Wayfinder постоянно перестраивает оба меню, в результате страница грузится около 2.68s при каждой загрузке.
Включение &cacheResults в вызове Wayfinder дало ускорение до 2.07s
Покопался в коде, понял следующее - при переходе со страницы на страницу Wayfinder заново выстраивает всю структуру и потом еще обрабатывает её, присваивая классы текущему пункту меню. Оптимизация hide sub menus описанная в инете не помогла: боковое меню стало работать быстрее, но оставалось еще верхнее меню, которое работало так же медленно.
Решил делать так: выстраивать меню целиком, сохранять его в кэше. Потом для бокового меню отдельно фильтровать скриптом и присваивать классы.
В итоге родился вот такой сниппет:
/* Snippet WayfinderKSV
* Author: Sergey Kravtsov
* Author email: [email protected]
*/
//Get the current context, not necessarily, but I have multisite
$context=$modx->getOption('context_name')."_";
switch($mode) // In the call of the snippet will indicate the mode
{
case 'topmenu': //Top menu
$key=$context.'wftopmenu'; //Cachekey name
$snippet='Wayfinder'; //Wayfinder params
$params=array(
'startId' => 0,
'outerTpl'=>'topMenuOuterTpl',
'innerTpl'=>'topMenuInnerTpl',
'rowTpl'=>'topMenuRowTpl',
'level'=>4
);
break;
case 'production'://Side menu
$key=$context.'wfprodmenu';//Cache key name
$snippet='Wayfinder'; //Wayfinder paramenters
$params=array(
'startId' => $modx->getOption('product_id'),
'hereClass'=>' ', //Set spaces, so Wayfinder will not add here and active classes
'selfClass'=>' ',
'rowTpl'=>'sideMenuRowTpl',
'rowIdPrefix'=>'sm_', //There are keys needed for filtering below
'levelClass'=>'level_',
'outerClass'=>'prodmenu',
'level'=>4
);
break;
}
$cached_wf = $modx->cacheManager->get($key); //Get the saved version of the cache
if(!$cached_wf ) //If not found
{
$wf= $modx->runSnippet($snippet,$params); //Start Wayfinder
$cacheres=$modx->cacheManager->set($key,$wf,7200); //Caching Wayfinder output
}
else $wf=$cached_wf;
if($mode=='production' ) //Filter, if sidemenu
{
$id=$modx->resource->get('id');
$parents=$modx->getParentIds($id);
$root_parents=array(0,$modx->getOption('product_id'));
$parents = array_diff($parents, $root_parents);
$find=array();
$replace=array();
$i=0;
foreach($parents as $p){
$find[$i]='id="sm_'.$p.'" class="';
$replace[$i]=$find[$i].' current '; //all "parent" node in the menu put the class 'current'
$i++;
}
$find[$i]='id="sm_'.$id.'" class="';
$replace[$i]=$find[$i].' active current '; //set the current document 'active current'
$wf=str_replace($find,$replace,$wf);
}
echo $wf;
Теперь с помощью CSS спрячем всё лишнее:
#sidemenu-box ul.prodmenu li.level_2,
#sidemenu-box ul.prodmenu li.level_3,
#sidemenu-box ul.prodmenu li.level_4,
#sidemenu-box ul.prodmenu li.level_5,
#sidemenu-box ul.prodmenu li.level_6{
display:none;
}
#sidemenu-box ul.prodmenu li.current ul li.level_2,
#sidemenu-box ul.prodmenu li.current ul li.current ul li.level_3,
#sidemenu-box ul.prodmenu li.current ul li.current ul li.current ul li.level_3,
#sidemenu-box ul.prodmenu li.current ul li.current ul li.current ul li.current ul li.level_4,
#sidemenu-box ul.prodmenu li.current ul li.current ul li.current ul li.current ul li.current ul li.level_5{
display:inherit;
}
Сам вызов сниппета такой:
[[WayfinderKSV? &mode=`production` ]]
Результаты работы такие (время загрузки страницы):
1. Без фильтрации (верхнее меню) - 707ms
2. С фильтрацией (боковое меню) 1.2s
Исходное время 2.68s, то есть достигнуто ускорение минимум в 2 раза.
Метод, возможно, не самый красивый, но:
1. Удобный, т.к. не требует ломать чужие сниппеты
2. Может быть применен к любым другим сниппетам.
Ниже прикрепил файликом отдельным, с русскими комментами.
[ed. note: sergey.kravtsov last edited this post 12 years, 5 months ago.]