El menú de Magento 2 desaparece
El menú principal de Magento 2 puede desaparecer por diferentes causas.
Block catalog.topnav y ESI de Varnish
El menú principal de Magento 2 está definido en el bloque catalog.topnav
. Este bloque tiene un
atributo ttl con el tiempo 3600 segundos equivalente a 1 hora. El ttl es Time To Live, el tiempo de vida de un
proceso. En este caso el tiempo de vida del caché del bloque del menú.
<block class="Magento\Theme\Block\Html\Topmenu" name="catalog.topnav" template="Magento_Theme::html/topmenu.phtml" ttl="3600" before="-"/>
Este atributo ttl opcional sirve para dar orden al sistema de caché de Magento invalidar el caché del menú cada hora. Por defecto el caché del contenido público se refresca cada 86400 segundos, equivalente a 1 día, pero los bloques pueden tener diferentes ttl.
Los bloques que tienen ttl, tendrán su propia petición esi de Varnish. En este caso el bloque catalog.topnav
tendrá
una petición como la siguiente:
ReqURL /tienda/page_cache/block/esi/blocks/%5B%22catalog.topnav%22%5D/handles/WyJkZWZhdWx0IiwiY21zX25vcm91dGVfaW5kZXgiLCJjbXNfcGFnZV92aWV3Il0%3D/
El segmento que va después de handles está codificado con base64. Si queremos saber la información, tendremos que descodificarlo.
Una de las maneras de descodificar es usando la función adob()
de Javascript. Recordar descodificar antes
la url con decodeURIComponent()
.
atob(decodeURIComponent('WyJkZWZhdWx0IiwiY21zX25vcm91dGVfaW5kZXgiLCJjbXNfcGFnZV92aWV3Il0%3D'));
# Output, un array de handles
'["default","cms_noroute_index","cms_page_view"]
Es decir, esta petición trae caché del bloque catalog.topnav
para los handles default, cms_noroute_index y cms_page_view
.
Mala configuración del sistema de caché: Varnish vs Built In
Si hemos configurado el Full page caché con Varnish y no tenemos este servicio instalado y bien configurado, el menú no aparecerá porque Magento intentará traer los datos del caché de Varnish (ESI: Varnish Edge Side Includes) y no hay.
La ruta de la configuración es Stores > Settings > Configuration > Advanced > System > Full Page Cache.
app/code/Magento/PageCache/Observer/ProcessLayoutRenderElement.php
/**
* Replace the output of the block, containing ttl attribute, with ESI tag
*
* @param \Magento\Framework\View\Element\AbstractBlock $block
* @param \Magento\Framework\View\Layout $layout
* @return string
*/
private function _wrapEsi(
\Magento\Framework\View\Element\AbstractBlock $block,
\Magento\Framework\View\Layout $layout
) {
$handles = $layout->getUpdate()->getHandles();
$pageSpecificHandles = $this->entitySpecificHandlesList->getHandles();
$url = $block->getUrl(
'page_cache/block/esi',
[
'blocks' => $this->jsonSerializer->serialize([$block->getNameInLayout()]),
'handles' => $this->base64jsonSerializer->serialize(
array_values(array_diff($handles, $pageSpecificHandles))
)
]
);
// Varnish does not support ESI over HTTPS must change to HTTP
$url = ($url && substr($url, 0, 5) === 'https') ? 'http' . substr($url, 5) : $url;
return sprintf('<esi:include src="%s" />', $url);
}
Revisión del fichero VCL de configuraciones de Varnish
Si Varnish falla para la petición del fragmento del Top Menú, el menú tampoco se mostrará. En este caso verás
algo como Varnish Service Unvailable
en el código fuente de la página. Para ver logs de Varnish, ejecutamos
el siguiente comando con el usuario root
sudo varnishlog | grep -B 2 -A 2 -i 'VCL_Error'
# ó
sudo varnishlog -q 'RespStatus == 503' -g request
El output puede ser como el siguiente:
VCL_call HIT
VCL_return restart
VCL_Error Too many restarts
RespProtocol HTTP/1.1
RespStatus 503
RespReason Service Unavailable
Entonces vamos a revisar el fichero de configuraciones en nuestro servidor /etc/varnish/default.vcl
con el fichero vcl de Magento.
Los comparamos. El error puede ser porque tenemos el vcl desactualizado.
Commando para generar el fichero vcl de Magento para Varnish
bin/magento varnish:vcl:generate --export-version=6 --access-list localhost --backend-host localhost --backend-port 8080 --output-file var/default.vcl
Solución temporal
Si tenemos prisas y todo lo comentado anteriormente no da resultados, nos queda una solución rápida, que es eliminar
el atributo opcional ttl del block catalog.topnav
. Esta solución afectará el performance de la WEB, por lo tanto
tiene que ser algo urgente y temporal. El menú está casi en todas las páginas. Una página lenta puede afectar negativamente las
ventas.