I am using magento2-1.0.0-beta4
I have copied the checkout.root
block from app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml
to the product page.
Everything is working fine, until I enable the page_cache
. That block is having cacheable="false"
in the Layout XML.
Now when I open my product page, the block does not get rendered at all.
If I understood the page cache correctly, it should load such blocks via an AJAX call. But there does not seem to happen such an AJAX call as my break point in \Magento\PageCache\Controller\Block\Render::execute
is never hit.
When opening /checkout/
or /checkout/cart/
everything works. But there also does not seem to happen an AJAX call. Instead the whole page does not seem to be rendered from the cache, which makes sense for the cart.
So should I simply exclude the product view page from the page_cache
?
But I did not find a way to do so?
Best Answer
This issue is still reproducible on Magento 2.0.0 Stable.
There is a feature in Magento 2 exception handling, which prevents rendering of broken blocks while all other blocks are still rendered. In developer mode it is disabled and all exceptions are displayed right in browser. In default and production modes, if exception occurs during block rendering, the block will just be removed from the output (corresponding exception is still logged to var/log/system.log). See
\Magento\Framework\View\Layout::renderNonCachedElement()
.Following exception occurs during checkout block rendering on product page and that is why this block is missing:
main.CRITICAL: No such entity with customerId = [] []
.The reason for this exception is that customer data in session storage is in inconsistent state (
customerLoggedIn == true
and customer data is missing) after\Magento\PageCache\Model\Layout\DepersonalizePlugin::afterGenerateXml()
execution. This plugin closes current PHP session and thus removes customer data from session storage. This happens only if page is fully cacheable (and it actually is).Page is considered to be cacheable by page cache module only if its layout does not contain blocks with
cacheable="false"
. Adding this attribute will not make this block loaded by Ajax (as assumed in the question). To have some block being loaded by Ajax, this block should have declared property_isScopePrivate
which is set totrue
, moreover, there should be no blocks withcacheable="false"
on the page. See\Magento\PageCache\Observer\ProcessLayoutRenderElement::execute()
andmage.pageCache._replacePlaceholder()
in Magento/PageCache/view/frontend/web/js/page-cache.js. Also check high-level docs in page cache module readmeProduct page should not be cacheable since
cacheable="false"
is set for checkout block, however it is, due to known issue Uncacheable blocks being cached. Until this issue is resolved, the following workaround may be used (don't ask me why it works, it is a long story):\Magento\Framework\Pricing\Render\Layout::__construct
['cacheable' => $generalLayout->isCacheable()]
to['cacheable' => false]
This should not harm because product pages will not be cached anyway after adding checkout block
Another question is, do you really want to make product pages non-cacheable by built-in page cache or Varnish?