Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
REAL USE CASES OF PERFORMANCE OPTIMISATION
MAGENTO 2
by Max Pronko
ABOUT ME
➤ former Magento core member
➤ CTO at TheIrishStore and
GiftsDirect
➤ Founder of Pronko Consulting
➤ 7+ years of ...
AGENDA
➤ Performance Optimisation
➤ eCommerce Website Data
➤ Real Improvements
➤ Varnish
➤ Q&A
www.maxpronko.com
PERFORMANCE
www.maxpronko.com
PERFORMANCE
Refers to the speed in which pages are
downloaded and displayed on the user’s browser
www.maxpronko.com
IS PERFORMANCE IMPORTANT?
➤ Customer Experience
➤ Conversion Rate
➤ Organic Search
www.maxpronko.com
PERFORMANCE OPTIMISATION
www.maxpronko.com Image: Fast and Furious
STEPS OF PERFORMANCE TUNING
➤ Assess the problem
➤ Measure performance
➤ Identify part of the system critical for performa...
ECOMMERCE WEBSITE PROFILE
➤ Seasonal business
➤ 4k products
➤ 500 Configurable Products
➤ 2k Configurable Variations
➤ 1.5k ...
BEFORE VS AFTER OPTIMISATION
Before
Category Page
Product Page
Shopping Cart
Checkout Index
0 500 1000 1500 2000
Magento 2...
BEFORE VS AFTER OPTIMISATION
After
Category Page
Product Page
Shopping Cart
Checkout Index
0 500 1000 1500 2000
Magento 2 ...
MAGENTO 2 APPLICATION
www.maxpronko.com
MAGENTO 2 APPLICATION
Optimisations
www.maxpronko.com
MAGENTO 2 APPLICATION
914 318ms ms
Before After
www.maxpronko.com
LET’S START
Image: mezzotint.dewww.maxpronko.com
DISABLE UNUSED
CORE MODULES
www.maxpronko.com
FOR EXISTING MAGENTO 2 INSTALLATION
> bin/magento module:disable Magento_Downloadable
> bin/magento setup:upgrade
> bin/ma...
COMPOSER.JSON
{
"repositories": [

{

"type": "composer",

"url": "https://repo.magento.com/"

}

],
"require": {
"magento...
WHAT TO DISABLE?
➤ Extra Languages
➤ Offline shipping and payments
➤ Backup, Captcha, Persistent, Rss
➤ Msrp, Send Friend, W...
DISABLE UNUSED FEATURES
www.maxpronko.com
HOW TO DISABLE
FEATURES?
www.maxpronko.com
DISABLING FEATURES
➤ Observer
➤ Plugin
➤ Layout
www.maxpronko.com
MAGENTO REPORTS
➤ vendor/magento/module-reports/etc/frontend/events.xml
<config>

<event name="catalog_product_compare_rem...
DISABLE OBSERVERS
➤ app/code/Pronko/Performance/etc/frontend/events.xml


<config>

<event name="catalog_product_compare_r...
DISABLE VIA PLUGIN
➤ app/code/Pronko/Performance/etc/di.xml


<config>

<type name="MagentoBackendModelMenu">

<arguments>...
REMOVE BLOCKS FROM LAYOUT
➤ Debug Hints
➤ Find non-used Blocks
➤ Remove it
www.maxpronko.com
REMOVE BLOCKS FROM LAYOUT
➤ default.xml


<referenceBlock name="copyright" remove="true" />

<referenceBlock name="store_s...
HOW ABOUT BLOCK
CACHE?
www.maxpronko.com
BLOCK CACHE
➤ Reduce number of Database queries
➤ Collection Load
➤ Template processing
➤ Eliminate Inline Translation
www...
ABSTRACT BLOCK CLASS
public function toHtml()

{

$html = $this->_loadCache();

if ($html === false) {



$this->_beforeTo...
ABSTRACT BLOCK CLASS
public function toHtml()

{

$html = $this->_loadCache();

if ($html === false) {



$this->_beforeTo...
ABSTRACT BLOCK CLASS
protected function _loadCache()

{

if ($this->getCacheLifetime() === null || !$this->_cacheState-
>i...
CATEGORY PAGE
www.maxpronko.com
CACHED BLOCKS
Navigation
Product
Price
www.maxpronko.com
Breadcrumb
Layered
Navigation
Product
Product List
NON-CACHED BLOCKS
www.maxpronko.com
LETS USE BLOCK CACHE
www.maxpronko.com
BREADCRUMBS BLOCK
default.xml
<referenceBlock name="breadcrumbs">

<arguments>

<argument name="cache_lifetime" xsi:type="...
LAYERED NAVIGATION BLOCK
➤ Layer State Key
➤ Category
➤ Customer Group
➤ Store
➤ Filters
➤ Currency
www.maxpronko.com
LAYERED NAVIGATION BLOCK
<referenceBlock name="catalog.leftnav">

<arguments>

<argument name="cache_lifetime" xsi:type="n...
LAYERED NAVIGATION PLUGIN DECLARATION
di.xml
<config>

<type name="MagentoLayeredNavigationBlockNavigation">

<plugin name...
LAYERED NAVIGATION PLUGIN
class LayeredNavigationPlugin

{

public function afterGetCacheKey(Navigation $block, $cacheKey)...
PRODUCT LIST
<?php

$_productCollection = $block->getLoadedProductCollection();

$_helper = $this->helper('MagentoCatalogH...
PRODUCT LIST
➤ Copy list.phtml and move foreach from the template
➤ Create new ProductList block class
➤ Create new Produc...
NEW PRODUCT LIST TEMPLATE
<?php if (!$block->getLoadedProductCollection()->count()): ?>

<div class="message info empty"><...
CATEGORY PAGE - CACHED
www.maxpronko.com
RELATED PRODUCTS
Product Page
www.maxpronko.com
PRODUCT PAGE
www.maxpronko.com
33 Attributes EAV Tables
ACTIONS
➤ Don’t use getAttributesUsedInProductListing() method
➤ Decrease number of attributes loaded
➤ Decrease number of...
ATTRIBUTES CONFIG
namespace MagentoCatalogModel;



class Config extends MagentoEavModelConfig

{
public function getProdu...
ATTRIBUTES CONFIG
namespace PronkoPerformanceModelConfig;



class Related extends MagentoCatalogModelConfig

{

const XML...
CONFIGURATION
<virtualType name="PronkoPerformanceProductRelatedContext" type="MagentoCatalogBlockProductContext">

<argum...
CATALOG_PRODUCT_VIEW.XML
<referenceBlock name="catalog.product.related" remove="true" />
<referenceContainer name="content...
3RD PARTY MODULES
www.maxpronko.com
DOUBLE CHECK
➤ HTTP POST requests
➤ Collections usage
➤ Slow file/database operations
➤ Performance Tests on staging server...
VARNISH
www.maxpronko.com
X-MAGENTO-VARY
➤ Customer Logged In
➤ Customer Group
➤ Customer Segment (EE only)
➤ Store
➤ Currency
➤ Tax Rates
www.maxpr...
X-MAGENTO-VARY
X-Magento-Vary = MD5(context data)
sub vcl_hash {

if (req.http.cookie ~ "X-Magento-Vary=") {

hash_data(re...
VARNISH HASH DATA
➤ 1 Website, no customer groups, same content for guest and logged in
➤ GeoIP functionality
sub vcl_hash...
VARNISH PERFORMANCE BEST PRACTICES
➤ Warmup pages after website content update
➤ Plan content changes ahead
➤ Run cron to ...
WHAT ELSE?
www.maxpronko.com
MORE PERFORMANCE OPTIMISATIONS
➤ Remove Compare Products feature
➤ Minify and merge JavaScript and CSS
➤ Enable Async Orde...
TRACKING AND MARKETING
➤ Asynchronous script loading for everything
➤ Google Tag Manager is good for async
➤ Avoid additio...
PERFORMANCE TOOLS
www.maxpronko.com
SUMMARY
➤ Disable functionality
➤ Use block cache
➤ Optimise/reduce database queries
➤ Remove unused blocks, observers
➤ W...
THANK YOU
max_pronko
Q&A Time
www.maxpronko.com
Upcoming SlideShare
Loading in …5
×

Real use cases of performance optimization in magento 2

17,027 views

Published on

Is performance in Magento 2 the same as or slower than Magento 1? There are lots of discussions and debates about Magento 2’s performance. All debates are around sample data and Vanilla platform comparison. In this topic Max will share optimisations techniques to have solid page load times for Magento 2.

Also visit my blog: www.maxpronko.com

Published in: Software

Real use cases of performance optimization in magento 2

  1. 1. REAL USE CASES OF PERFORMANCE OPTIMISATION MAGENTO 2 by Max Pronko
  2. 2. ABOUT ME ➤ former Magento core member ➤ CTO at TheIrishStore and GiftsDirect ➤ Founder of Pronko Consulting ➤ 7+ years of Magento Experience ➤ Magento 2 Blog
  3. 3. AGENDA ➤ Performance Optimisation ➤ eCommerce Website Data ➤ Real Improvements ➤ Varnish ➤ Q&A www.maxpronko.com
  4. 4. PERFORMANCE www.maxpronko.com
  5. 5. PERFORMANCE Refers to the speed in which pages are downloaded and displayed on the user’s browser www.maxpronko.com
  6. 6. IS PERFORMANCE IMPORTANT? ➤ Customer Experience ➤ Conversion Rate ➤ Organic Search www.maxpronko.com
  7. 7. PERFORMANCE OPTIMISATION www.maxpronko.com Image: Fast and Furious
  8. 8. STEPS OF PERFORMANCE TUNING ➤ Assess the problem ➤ Measure performance ➤ Identify part of the system critical for performance improvement ➤ Modify part of system to remove the bottleneck ➤ Measure the performance after modification ➤ If better, adopt it or revert https://en.wikipedia.org/wiki/Performance_tuningwww.maxpronko.com
  9. 9. ECOMMERCE WEBSITE PROFILE ➤ Seasonal business ➤ 4k products ➤ 500 Configurable Products ➤ 2k Configurable Variations ➤ 1.5k Simple Products ➤ 500 Categories ➤ Average Order Value: $100 ➤ 2-3 products per Order www.maxpronko.com
  10. 10. BEFORE VS AFTER OPTIMISATION Before Category Page Product Page Shopping Cart Checkout Index 0 500 1000 1500 2000 Magento 2 Application www.maxpronko.com
  11. 11. BEFORE VS AFTER OPTIMISATION After Category Page Product Page Shopping Cart Checkout Index 0 500 1000 1500 2000 Magento 2 Application www.maxpronko.com
  12. 12. MAGENTO 2 APPLICATION www.maxpronko.com
  13. 13. MAGENTO 2 APPLICATION Optimisations www.maxpronko.com
  14. 14. MAGENTO 2 APPLICATION 914 318ms ms Before After www.maxpronko.com
  15. 15. LET’S START Image: mezzotint.dewww.maxpronko.com
  16. 16. DISABLE UNUSED CORE MODULES www.maxpronko.com
  17. 17. FOR EXISTING MAGENTO 2 INSTALLATION > bin/magento module:disable Magento_Downloadable > bin/magento setup:upgrade > bin/magento setup:di:compile > bin/magento setup:static-content:deploy www.maxpronko.com
  18. 18. COMPOSER.JSON { "repositories": [
 {
 "type": "composer",
 "url": "https://repo.magento.com/"
 }
 ], "require": { "magento/composer": "~1.0.0",
 "magento/framework": "100.1.1",
 "magento/language-en_us": "100.1.0",
 "magento/magento-composer-installer": "*",
 "magento/magento2-base": “2.1.1”, ... }, } www.maxpronko.com
  19. 19. WHAT TO DISABLE? ➤ Extra Languages ➤ Offline shipping and payments ➤ Backup, Captcha, Persistent, Rss ➤ Msrp, Send Friend, Weee ➤ Multishipping, Checkout Agreements ➤ Product types? ➤ More… depends on project www.maxpronko.com
  20. 20. DISABLE UNUSED FEATURES www.maxpronko.com
  21. 21. HOW TO DISABLE FEATURES? www.maxpronko.com
  22. 22. DISABLING FEATURES ➤ Observer ➤ Plugin ➤ Layout www.maxpronko.com
  23. 23. MAGENTO REPORTS ➤ vendor/magento/module-reports/etc/frontend/events.xml <config>
 <event name="catalog_product_compare_remove_product">
 <observer name="reports" instance="MagentoReportsObserverCatalogProductCompareClearObserver" />
 </event>
 <event name="customer_login">
 <observer name="reports" instance="MagentoReportsObserverCustomerLoginObserver" />
 </event>
 <event name="customer_logout">
 <observer name="reports" instance="MagentoReportsObserverCustomerLogoutObserver" />
 </event>
 <event name="catalog_controller_product_view">
 <observer name="reports" instance="MagentoReportsObserverCatalogProductViewObserver" />
 </event>
 <event name="sendfriend_product">
 <observer name="reports" instance="MagentoReportsObserverSendfriendProductObserver" />
 </event>
 <event name="catalog_product_compare_add_product">
 <observer name="reports" instance="MagentoReportsObserverCatalogProductCompareAddProductObserver" />
 </event>
 <event name="catalog_product_compare_item_collection_clear">
 <observer name="reports" instance="MagentoReportsObserverCatalogProductCompareClearObserver" />
 </event>
 <event name="sales_quote_item_save_before">
 <observer name="reports" instance="MagentoReportsObserverCheckoutCartAddProductObserver" />
 </event>
 <event name="wishlist_add_product">
 <observer name="reports" instance="MagentoReportsObserverWishlistAddProductObserver" />
 </event>
 <event name="wishlist_share">
 <observer name="reports" instance="MagentoReportsObserverWishlistShareObserver" />
 </event>
 </config>
 www.maxpronko.com
  24. 24. DISABLE OBSERVERS ➤ app/code/Pronko/Performance/etc/frontend/events.xml 
 <config>
 <event name="catalog_product_compare_remove_product">
 <observer name="reports" disabled="true" />
 </event>
 <event name="catalog_controller_product_view">
 <observer name="reports" disabled="true" />
 </event>
 <event name="sendfriend_product">
 <observer name="reports" disabled="true" />
 </event>
 <event name="catalog_product_compare_add_product">
 <observer name="reports" disabled="true" />
 </event>
 <event name="catalog_product_compare_item_collection_clear">
 <observer name="reports" disabled="true" />
 </event>
 <event name="wishlist_add_product">
 <observer name="reports" disabled="true" />
 </event>
 <event name="wishlist_share">
 <observer name="reports" disabled="true" />
 </event>
 </config>
 www.maxpronko.com
  25. 25. DISABLE VIA PLUGIN ➤ app/code/Pronko/Performance/etc/di.xml 
 <config>
 <type name="MagentoBackendModelMenu">
 <arguments>
 <argument name="logger" xsi:type="object">PsrLogNullLogger</argument>
 </arguments>
 </type>
 <type name="MagentoFrameworkCacheInvalidateLogger">
 <plugin name="DisableCacheInvalidateLog" type="PronkoPerformancePluginInvalidateLoggerPlugin" />
 </type>
 </config> www.maxpronko.com
  26. 26. REMOVE BLOCKS FROM LAYOUT ➤ Debug Hints ➤ Find non-used Blocks ➤ Remove it www.maxpronko.com
  27. 27. REMOVE BLOCKS FROM LAYOUT ➤ default.xml 
 <referenceBlock name="copyright" remove="true" />
 <referenceBlock name="store_switcher" remove="true" />
 <referenceBlock name="store_language" remove="true" />
 <referenceBlock name="store.settings.language" remove="true" />
 <referenceBlock name="translate" remove="true" /> ➤ catalog_product_view.xml 
 <referenceBlock name="product.price.tier" remove="true"/>
 <referenceBlock name="product.info.upsell" remove="true"/>
 <referenceBlock name="product.info.extrahint.qtyincrements" remove="true"/>
 <referenceBlock name="product.tooltip" remove="true"/>
 <referenceBlock name="product.info.mailto" remove="true"/> www.maxpronko.com
  28. 28. HOW ABOUT BLOCK CACHE? www.maxpronko.com
  29. 29. BLOCK CACHE ➤ Reduce number of Database queries ➤ Collection Load ➤ Template processing ➤ Eliminate Inline Translation www.maxpronko.com
  30. 30. ABSTRACT BLOCK CLASS public function toHtml()
 {
 $html = $this->_loadCache();
 if ($html === false) {
 
 $this->_beforeToHtml();
 $html = $this->_toHtml();
 $this->_saveCache($html);
 
 }
 $html = $this->_afterToHtml($html);
 
 return $html;
 } www.maxpronko.com
  31. 31. ABSTRACT BLOCK CLASS public function toHtml()
 {
 $html = $this->_loadCache();
 if ($html === false) {
 
 $this->_beforeToHtml();
 $html = $this->_toHtml();
 $this->_saveCache($html);
 
 }
 $html = $this->_afterToHtml($html);
 
 return $html;
 } no more final :) www.maxpronko.com
  32. 32. ABSTRACT BLOCK CLASS protected function _loadCache()
 {
 if ($this->getCacheLifetime() === null || !$this->_cacheState- >isEnabled(self::CACHE_GROUP)) {
 return false;
 }
 $cacheKey = $this->getCacheKey();
 $cacheData = $this->_cache->load($cacheKey);
 if ($cacheData) {
 $cacheData = str_replace(//placeholder, //value,
 $cacheData
 );
 }
 return $cacheData;
 } www.maxpronko.com
  33. 33. CATEGORY PAGE www.maxpronko.com
  34. 34. CACHED BLOCKS Navigation Product Price www.maxpronko.com
  35. 35. Breadcrumb Layered Navigation Product Product List NON-CACHED BLOCKS www.maxpronko.com
  36. 36. LETS USE BLOCK CACHE www.maxpronko.com
  37. 37. BREADCRUMBS BLOCK default.xml <referenceBlock name="breadcrumbs">
 <arguments>
 <argument name="cache_lifetime" xsi:type="string">604800</argument>
 </arguments>
 </referenceBlock> www.maxpronko.com
  38. 38. LAYERED NAVIGATION BLOCK ➤ Layer State Key ➤ Category ➤ Customer Group ➤ Store ➤ Filters ➤ Currency www.maxpronko.com
  39. 39. LAYERED NAVIGATION BLOCK <referenceBlock name="catalog.leftnav">
 <arguments>
 <argument name="cache_lifetime" xsi:type="number">604800</argument>
 </arguments>
 </referenceBlock> catalog_category_view.xml www.maxpronko.com
  40. 40. LAYERED NAVIGATION PLUGIN DECLARATION di.xml <config>
 <type name="MagentoLayeredNavigationBlockNavigation">
 <plugin name="LayeredNavigationCacheKey" type="PronkoPerformancePlugin LayeredNavigationPlugin"/>
 </type>
 <type name="MagentoLayeredNavigationBlockNavigationCategory">
 <plugin name="LayeredNavigationCacheKey" type="PronkoPerformancePlugin LayeredNavigationPlugin"/>
 </type>
 </config> www.maxpronko.com
  41. 41. LAYERED NAVIGATION PLUGIN class LayeredNavigationPlugin
 {
 public function afterGetCacheKey(Navigation $block, $cacheKey)
 {
 $cacheKey .= $this->priceCurrency->getCurrency()->getCurrencyCode();
 
 $category = $block->getLayer()->getCurrentCategory();
 if ($category) {
 $cacheKey .= $category->getId();
 }
 
 $stateKey = $block->getLayer()->getStateKey();
 if ($stateKey) {
 $cacheKey .= $stateKey;
 }
 
 $cacheKey .= $this->toolbarModel->getCurrentPage();
 $cacheKey .= $this->toolbarModel->getDirection();
 $cacheKey .= $this->toolbarModel->getLimit();
 $cacheKey .= $this->toolbarModel->getMode();
 $cacheKey .= $this->toolbarModel->getOrder();
 
 return $cacheKey;
 }
 } www.maxpronko.com
  42. 42. PRODUCT LIST <?php
 $_productCollection = $block->getLoadedProductCollection();
 $_helper = $this->helper('MagentoCatalogHelperOutput');
 ?>
 <?php if (!$_productCollection->count()): ?>
 <div class="message info empty"><div><?php /* @escapeNotVerified */ echo __('We can't find products matching the selection.') ?></div></div>
 <?php else: ?>
 <?php echo $block->getToolbarHtml() ?>
 <?php echo $block->getAdditionalHtml() ?>
 <?php
 if ($block->getMode() == 'grid') {
 $viewMode = 'grid';
 $image = 'category_page_grid';
 $showDescription = false;
 $templateType = MagentoCatalogBlockProductReviewRendererInterface::SHORT_VIEW;
 } else {
 $viewMode = 'list';
 $image = 'category_page_list';
 $showDescription = true;
 $templateType = MagentoCatalogBlockProductReviewRendererInterface::FULL_VIEW;
 }
 /**
 * Position for actions regarding image size changing in vde if needed
 */
 $pos = $block->getPositioned();
 ?>
 <div class="products wrapper <?php /* @escapeNotVerified */ echo $viewMode; ?> products-<?php /* @escapeNotVerified */ echo $viewMode; ?>">
 <?php $iterator = 1; ?>
 <ol class="products list items product-items">
 <?php /** @var $_product MagentoCatalogModelProduct */ ?>
 <?php foreach ($_productCollection as $_product): ?>
 <?php /* @escapeNotVerified */ echo($iterator++ == 1) ? '<li class="item product product-item">' : '</li><li class="item product product-item">' ?>
 <div class="product-item-info" data-container="product-grid">
 <?php
 $productImage = $block->getImage($_product, $image);
 if ($pos != null) {
 $position = ' style="left:' . $productImage->getWidth() . 'px;'
 . 'top:' . $productImage->getHeight() . 'px;"';
 }
 ?>
 <?php // Product Image ?>
 <a href="<?php /* @escapeNotVerified */ echo $_product->getProductUrl() ?>" class="product photo product-item-photo" tabindex="-1">
 <?php echo $productImage->toHtml(); ?>
 </a>
 <div class="product details product-item-details">
 <?php
 $_productNameStripped = $block->stripTags($_product->getName(), null, true);
 ?>
 <strong class="product name product-item-name">
 <a class="product-item-link"
 href="<?php /* @escapeNotVerified */ echo $_product->getProductUrl() ?>">
 <?php /* @escapeNotVerified */ echo $_helper->productAttribute($_product, $_product->getName(), 'name'); ?>
 </a>
 </strong>
 <?php echo $block->getReviewsSummaryHtml($_product, $templateType); ?>
 <?php /* @escapeNotVerified */ echo $block->getProductPrice($_product) ?>
 <?php echo $block->getProductDetailsHtml($_product); ?>
 
 <div class="product-item-inner">
 <div class="product actions product-item-actions"<?php echo strpos($pos, $viewMode . '-actions') ? $position : ''; ?>>
 <div class="actions-primary"<?php echo strpos($pos, $viewMode . '-primary') ? $position : ''; ?>>
 <?php if ($_product->isSaleable()): ?>
 <?php $postParams = $block->getAddToCartPostParams($_product); ?>
 <form data-role="tocart-form" action="<?php /* @escapeNotVerified */ echo $postParams['action']; ?>" method="post">
 <input type="hidden" name="product" value="<?php /* @escapeNotVerified */ echo $postParams['data']['product']; ?>">
 <input type="hidden" name="<?php /* @escapeNotVerified */ echo Action::PARAM_NAME_URL_ENCODED; ?>" value="<?php /* @escapeNotVerified */ echo $postParams['data'][Action::PARAM_NAME_URL_ENCODED]; ?>">
 <?php echo $block->getBlockHtml('formkey')?>
 <button type="submit"
 title="<?php echo $block->escapeHtml(__('Add to Cart')); ?>"
 class="action tocart primary">
 <span><?php /* @escapeNotVerified */ echo __('Add to Cart') ?></span>
 </button>
 </form>
 <?php else: ?>
 <?php if ($_product->getIsSalable()): ?>
 <div class="stock available"><span><?php /* @escapeNotVerified */ echo __('In stock') ?></span></div>
 <?php else: ?>
 <div class="stock unavailable"><span><?php /* @escapeNotVerified */ echo __('Out of stock') ?></span></div>
 <?php endif; ?>
 <?php endif; ?>
 </div>
 <div data-role="add-to-links" class="actions-secondary"<?php echo strpos($pos, $viewMode . '-secondary') ? $position : ''; ?>>
 <?php if ($this->helper('MagentoWishlistHelperData')->isAllow()): ?>
 <a href="#"
 class="action towishlist"
 title="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
 aria-label="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
 data-post='<?php /* @escapeNotVerified */ echo $block->getAddToWishlistParams($_product); ?>'
 data-action="add-to-wishlist"
 role="button">
 <span><?php /* @escapeNotVerified */ echo __('Add to Wish List') ?></span>
 </a>
 <?php endif; ?>
 <?php
 $compareHelper = $this->helper('MagentoCatalogHelperProductCompare');
 ?>
 <a href="#"
 class="action tocompare"
 title="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
 aria-label="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
 data-post='<?php /* @escapeNotVerified */ echo $compareHelper->getPostDataParams($_product); ?>'
 role="button">
 <span><?php /* @escapeNotVerified */ echo __('Add to Compare') ?></span>
 </a>
 </div>

  43. 43. PRODUCT LIST ➤ Copy list.phtml and move foreach from the template ➤ Create new ProductList block class ➤ Create new Product/Item block class and item.phtml template ➤ Don’t forget about unique cacheKeyInfo ➤ Layered navigation, filter, toolbar, currency ➤ Set cache_lifetime value for both block classes www.maxpronko.com
  44. 44. NEW PRODUCT LIST TEMPLATE <?php if (!$block->getLoadedProductCollection()->count()): ?>
 <div class="message info empty"><div><?php /* @escapeNotVerified */ echo __('We can't find products matching the selection.') ?></ div></div>
 <?php else: ?>
 <?php echo $block->getToolbarHtml() ?>
 <?php echo $block->getAdditionalHtml() ?>
 <div class="products wrapper <?php /* @escapeNotVerified */ echo $block->getViewMode(); ?> products-<?php /* @escapeNotVerified */ $block->getViewMode(); ?>">
 <ol class="products list items product-items" itemscope itemtype="http://schema.org/ItemList">
 <?php echo $block->getProductsListHtml(); ?>
 </ol>
 </div>
 <?php echo $block->getToolbarHtml() ?>
 <?php if (!$block->isRedirectToCartEnabled()) : ?>
 <script type="text/x-magento-init">
 {
 "[data-role=tocart-form], .form.map.checkout": {
 "catalogAddToCart": {}
 }
 }
 </script>
 <?php endif; ?>
 <?php endif; ?> app/design/Pronko/default/Magento_Catalog/templates/product/list.phtml www.maxpronko.com
  45. 45. CATEGORY PAGE - CACHED www.maxpronko.com
  46. 46. RELATED PRODUCTS Product Page www.maxpronko.com
  47. 47. PRODUCT PAGE www.maxpronko.com 33 Attributes EAV Tables
  48. 48. ACTIONS ➤ Don’t use getAttributesUsedInProductListing() method ➤ Decrease number of attributes loaded ➤ Decrease number of EAV Tables usage on product page ➤ Enable block cache for each related product
  49. 49. ATTRIBUTES CONFIG namespace MagentoCatalogModel;
 
 class Config extends MagentoEavModelConfig
 { public function getProductAttributes()
 {
 if (is_null($this->_productAttributes)) {
 $this->_productAttributes = array_keys($this->getAttributesUsedInProductListing());
 }
 return $this->_productAttributes;
 } }
  50. 50. ATTRIBUTES CONFIG namespace PronkoPerformanceModelConfig;
 
 class Related extends MagentoCatalogModelConfig
 {
 const XML_PATH_PRODUCT_RELATED_ATTRIBUTES = 'catalog/related_product_attributes';
 
 public function getProductAttributes()
 {
 return array_keys($this->_scopeConfig->getValue(self::XML_PATH_PRODUCT_RELATED_ATTRIBUTES));
 }
 }

  51. 51. CONFIGURATION <virtualType name="PronkoPerformanceProductRelatedContext" type="MagentoCatalogBlockProductContext">
 <arguments>
 <argument name="catalogConfig" xsi:type="object">PronkoPerformanceModelConfigRelated</argument>
 </arguments>
 </virtualType>
 
 <type name="PronkoPerformanceBlockProductListRelated">
 <arguments>
 <argument name="context" xsi:type="object">PronkoPerformanceProductRelatedContext</argument>
 </arguments>
 </type> di.xml <config>
 <default>
 <catalog>
 <related_product_attributes>
 <name />
 <tax_class_id />
 <small_image />
 <image_label />
 <special_price />
 </related_product_attributes>
 </catalog>
 </default>
 </config>
 config.xml
  52. 52. CATALOG_PRODUCT_VIEW.XML <referenceBlock name="catalog.product.related" remove="true" /> <referenceContainer name="content.aside">
 <block class="PronkoPerformanceBlockProductListRelated" name="pronko.catalog.product.related" template="Magento_Catalog::product/list/items.phtml">
 <arguments>
 <argument name="type" xsi:type="string">related</argument>
 </arguments>
 </block>
 </referenceContainer>
  53. 53. 3RD PARTY MODULES www.maxpronko.com
  54. 54. DOUBLE CHECK ➤ HTTP POST requests ➤ Collections usage ➤ Slow file/database operations ➤ Performance Tests on staging server www.maxpronko.com
  55. 55. VARNISH www.maxpronko.com
  56. 56. X-MAGENTO-VARY ➤ Customer Logged In ➤ Customer Group ➤ Customer Segment (EE only) ➤ Store ➤ Currency ➤ Tax Rates www.maxpronko.com
  57. 57. X-MAGENTO-VARY X-Magento-Vary = MD5(context data) sub vcl_hash {
 if (req.http.cookie ~ "X-Magento-Vary=") {
 hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "1"));
 }
 
 if (req.http.host) {
 hash_data(req.http.host);
 } else {
 hash_data(server.ip);
 }
 } www.maxpronko.com
  58. 58. VARNISH HASH DATA ➤ 1 Website, no customer groups, same content for guest and logged in ➤ GeoIP functionality sub vcl_hash {
 if (req.url ~ "(?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid)=") { set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content| gclid)=([^&]+)", ""); set req.url = regsuball(req.url, "?(utm_source|utm_medium|utm_campaign|utm_content| gclid)=([^&]+)", "?"); set req.url = regsub(req.url, "?&", "?"); set req.url = regsub(req.url, "?$", ""); } hash_data(req.http.X-Currency);
 } www.maxpronko.com
  59. 59. VARNISH PERFORMANCE BEST PRACTICES ➤ Warmup pages after website content update ➤ Plan content changes ahead ➤ Run cron to clean up cache, reindex and warmup www.maxpronko.com
  60. 60. WHAT ELSE? www.maxpronko.com
  61. 61. MORE PERFORMANCE OPTIMISATIONS ➤ Remove Compare Products feature ➤ Minify and merge JavaScript and CSS ➤ Enable Async Order Grid ➤ Enable Async Transactional Emails www.maxpronko.com
  62. 62. TRACKING AND MARKETING ➤ Asynchronous script loading for everything ➤ Google Tag Manager is good for async ➤ Avoid additional collection loads for Facebook, adWords, etc. www.maxpronko.com
  63. 63. PERFORMANCE TOOLS www.maxpronko.com
  64. 64. SUMMARY ➤ Disable functionality ➤ Use block cache ➤ Optimise/reduce database queries ➤ Remove unused blocks, observers ➤ Warmup all pages ➤ Never stop improving your website www.maxpronko.com
  65. 65. THANK YOU max_pronko Q&A Time www.maxpronko.com

×