29
protected function _construct()
    {
        $this->addData(
            [
                'cache_lifetime' => false,
                'cache_tags' => array('MY_BLOCK'),
            ]
        );
    }

    public function getCacheKeyInfo()
    {
        return [];
    }

does not work. Why? How to disable the cache for block?

2
  • I suspect your block is inside another block that is also cached. For example, anything you put inside the footer block is cached because the footer block output is cached.
    – Smartie
    Commented Feb 24, 2016 at 12:24
  • @Smartie how to turn it off me? <referenceContainer name="content"> <block class="class" template="block.phtml" before="product.info.main"/> </referenceContainer>
    – gebuket
    Commented Feb 24, 2016 at 12:38

6 Answers 6

34

Blocks can be set as non-cacheable by setting the cacheable attribute false in layout XML files. For example

<block class="Block\Class" name="blockname" cacheable="false" />

Pages containing such blocks are not cached.

Also check How do disable caching of custom block

Edit: A single cacheable="false" will disable Full Page Caching for the whole page, making the pages sourcing from that layout file extremely slow! Check https://inviqa.com/blog/how-full-page-cache-works-magento-2

6
  • 27
    This is very inappropriate, a single cacheable="false" will disable Full Page Caching for the whole page, making the pages sourcing from that layout file extremely slow! Commented Nov 1, 2016 at 10:49
  • 2
    It's correct that it will disable cache for the whole page and already mentioned in the url I've shared magento.stackexchange.com/a/93473/9169. If you have a different approach feel free to share it as a new answer.
    – amitshree
    Commented Nov 1, 2016 at 15:52
  • Read this article, great explanation: inviqa.com/blog/how-full-page-cache-works-magento-2 Commented Nov 1, 2016 at 20:04
  • Awesome solution. Work like charm. Commented Feb 13, 2018 at 11:44
  • 2
    That's a bad idea for performance. =(
    – Kirby
    Commented Jul 2, 2018 at 17:52
18

It's important to understand why you don't want to cache block. If this is meant to show some session specific information then you should be looking into

One non-recommended option could be also custom controller what returns some data over ajax-call (with POST-method so it wouldn't be cached).

(!) cacheable="false" must not be used. Here will follow, WHY not:

A block with cacheable="false" will make the whole page uncached. It is not used for cache hole-punching. Also older M2 docs page use to says this (To create an uncacheable page, mark any block on that page as uncacheable in the layout using cacheable="false").

New docs is saying

What it does is that Varnish/Fastly modules will be sending due this attribute value always non-cacheable headers.

When we enable cachable="false" and while using Varnish/Fastly then browser side following headers are sent :

X-Magento-Cache-Debug:MISS
X-Magento-Cache-Control:max-age=0, must-revalidate, no-cache, no-store
Age: 0

For that can be debugged the Magento's page caching code on

vendor/magento/module-page-cache/Model/Layout/LayoutPlugin.php::afterGenerateXml
vendor/magento/module-page-cache/Model/Layout/LayoutPlugin.php::afterGetOutput

where first one should send public Cache-Control with TTL and second should send X-Magento-Tags for Varnish/Fastly.

Both are using isCacheable() check where this always returns FALSE due following check (check if in current layout there are any attributes:cacheable="false"):

$cacheableXml = !(bool)count($this->getXml()->xpath('//' . Element::TYPE_BLOCK . '[@cacheable="false"]'));

When we remove cacheable="false" then we start to get isCacheable() checks as TRUE and also get headers correctly on start-/category-/productpages.

X-Magento-Cache-Control:max-age=86400, public, s-maxage=86400
X-Magento-Cache-Debug:HIT
X-Magento-Cache-Hits:1
Age:32
3
  • 1
    So... what is the alternative solution?
    – Black
    Commented Feb 13, 2020 at 19:02
  • alternative must be taken case by case - what you need. if it's customer related then you need to define additional item-argument for Magento\Customer\CustomerData\SectionPoolInterface in etc/frontend/di.xml (ex. devdocs.magento.com/guides/v2.3/extension-dev-guide/cache/… ). if it should be block with dynamic data depending from product, then maybe it should be javascript component or widget. It really depends all on the case. Commented Mar 5, 2020 at 6:42
  • can you please add more details about using the sectionpoolinterface? I have some custom blocks using isScopeprivate variable. But I dont know how to replace that with alternate way. can you please help Commented Apr 23, 2020 at 10:15
16

I have made non-cacheable for Pricing block

<?php

namespace Custom\Module\Block\Pricing\Render;

class ExtendFinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox {

    public function getCacheLifetime()
    {
        return null;
    }

}
5
  • How did you replace FinalPriceBox with ExtendPriceBox using di.xml?
    – siddhesh
    Commented Jul 14, 2017 at 14:54
  • Yes using di.xml Commented Jul 18, 2017 at 16:39
  • @LeadDeveloper, he wants to know what you wrote into your di.xml
    – Black
    Commented Feb 13, 2020 at 19:02
  • @LeadDeveloper this is not working Commented Dec 4, 2020 at 10:17
  • This doesn't stop using ESI loading by varnish, and as such it doesn't get for example HTTP GET params from the parent request. Commented May 17, 2022 at 10:24
3

Try to avoid using cacheable="false" as this disables cache for the entire page and causes performance issues.

When using Varnish you can use the ttl attribute instead, like:

<block class="Block\Class" name="blockname" ttl="0" />

1

I wouldn't recommend using cacheable="false" since it's a "page cache breaker" as it states in Magento developer docs. If you make getCacheLifetime in the block to return null it doesn't stop making ESI requests for the block and ESI requests are not going to get any of the parent page GET context like category ID, etc.

If you remove the block in the layout and re-add with different name it with current dependencies to the block. For example:


<referenceBlock name="catalog.topnav" remove="true" />
<block class="Magento\Theme\Block\Html\Topmenu" name="custom.catalog.topnav" as="catalog.topnav" template="Magento_Theme::html/topmenu.phtml" >
    <!-- Find and put here dependencies that are currently injected to the removed block -->
</block>

This way this block is not loaded by ESI and it doesn't break the page cache.

0

You can add non-cacheable block only to custom pages. In other case, magento Page Cache will not work for these pages OR update information in block via ajax (magento section requests).

1
  • this solution is not working in magento 2.4.5 Commented Nov 8, 2022 at 13:35

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.