65
REAL USE CASES OF PERFORMANCE OPTIMISATION MAGENTO 2 by Max Pronko

Real use cases of performance optimization in magento 2

Embed Size (px)

Citation preview

Page 1: Real use cases of performance optimization in magento 2

REAL USE CASES OF PERFORMANCE OPTIMISATION MAGENTO 2

by Max Pronko

Page 2: Real use cases of performance optimization in magento 2

ABOUT ME

➤ former Magento core member

➤ CTO at TheIrishStore and GiftsDirect

➤ Founder of Pronko Consulting

➤ 7+ years of Magento Experience

➤ Magento 2 Blog

Page 3: Real use cases of performance optimization in magento 2

AGENDA

➤ Performance Optimisation

➤ eCommerce Website Data

➤ Real Improvements

➤ Varnish

➤ Q&A

www.maxpronko.com

Page 4: Real use cases of performance optimization in magento 2

PERFORMANCE

www.maxpronko.com

Page 5: Real use cases of performance optimization in magento 2

PERFORMANCERefers to the speed in which pages are

downloaded and displayed on the user’s browser

www.maxpronko.com

Page 6: Real use cases of performance optimization in magento 2

IS PERFORMANCE IMPORTANT?

➤ Customer Experience

➤ Conversion Rate

➤ Organic Search

www.maxpronko.com

Page 7: Real use cases of performance optimization in magento 2

PERFORMANCE OPTIMISATIONwww.maxpronko.com Image: Fast and Furious

Page 8: Real use cases of performance optimization in magento 2

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

Page 9: Real use cases of performance optimization in magento 2

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

Page 10: Real use cases of performance optimization in magento 2

BEFORE VS AFTER OPTIMISATION

Before

Category Page

Product Page

Shopping Cart

Checkout Index

0 500 1000 1500 2000

Magento 2 Application

www.maxpronko.com

Page 11: Real use cases of performance optimization in magento 2

BEFORE VS AFTER OPTIMISATION

After

Category Page

Product Page

Shopping Cart

Checkout Index

0 500 1000 1500 2000

Magento 2 Application

www.maxpronko.com

Page 12: Real use cases of performance optimization in magento 2

MAGENTO 2 APPLICATION

www.maxpronko.com

Page 13: Real use cases of performance optimization in magento 2

MAGENTO 2 APPLICATION

Optimisations

www.maxpronko.com

Page 14: Real use cases of performance optimization in magento 2

MAGENTO 2 APPLICATION

914 318ms ms

Before After

www.maxpronko.com

Page 15: Real use cases of performance optimization in magento 2

LET’S START

Image: mezzotint.dewww.maxpronko.com

Page 16: Real use cases of performance optimization in magento 2

DISABLE UNUSED CORE MODULES

www.maxpronko.com

Page 17: Real use cases of performance optimization in magento 2

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

Page 18: Real use cases of performance optimization in magento 2

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

Page 19: Real use cases of performance optimization in magento 2

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

Page 20: Real use cases of performance optimization in magento 2

DISABLE UNUSED FEATURES

www.maxpronko.com

Page 21: Real use cases of performance optimization in magento 2

HOW TO DISABLE FEATURES?

www.maxpronko.com

Page 22: Real use cases of performance optimization in magento 2

DISABLING FEATURES

➤ Observer

➤ Plugin

➤ Layout

www.maxpronko.com

Page 23: Real use cases of performance optimization in magento 2

MAGENTO REPORTS

➤ vendor/magento/module-reports/etc/frontend/events.xml <config> <event name="catalog_product_compare_remove_product"> <observer name="reports" instance="Magento\Reports\Observer\CatalogProductCompareClearObserver" /> </event> <event name="customer_login"> <observer name="reports" instance="Magento\Reports\Observer\CustomerLoginObserver" /> </event> <event name="customer_logout"> <observer name="reports" instance="Magento\Reports\Observer\CustomerLogoutObserver" /> </event> <event name="catalog_controller_product_view"> <observer name="reports" instance="Magento\Reports\Observer\CatalogProductViewObserver" /> </event> <event name="sendfriend_product"> <observer name="reports" instance="Magento\Reports\Observer\SendfriendProductObserver" /> </event> <event name="catalog_product_compare_add_product"> <observer name="reports" instance="Magento\Reports\Observer\CatalogProductCompareAddProductObserver" /> </event> <event name="catalog_product_compare_item_collection_clear"> <observer name="reports" instance="Magento\Reports\Observer\CatalogProductCompareClearObserver" /> </event> <event name="sales_quote_item_save_before"> <observer name="reports" instance="Magento\Reports\Observer\CheckoutCartAddProductObserver" /> </event> <event name="wishlist_add_product"> <observer name="reports" instance="Magento\Reports\Observer\WishlistAddProductObserver" /> </event> <event name="wishlist_share"> <observer name="reports" instance="Magento\Reports\Observer\WishlistShareObserver" /> </event> </config>

www.maxpronko.com

Page 24: Real use cases of performance optimization in magento 2

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

Page 25: Real use cases of performance optimization in magento 2

DISABLE VIA PLUGIN

➤ app/code/Pronko/Performance/etc/di.xml <config> <type name="Magento\Backend\Model\Menu"> <arguments> <argument name="logger" xsi:type="object">Psr\Log\NullLogger</argument> </arguments> </type> <type name="Magento\Framework\Cache\InvalidateLogger"> <plugin name="DisableCacheInvalidateLog" type="Pronko\Performance\Plugin\InvalidateLoggerPlugin" /> </type> </config>

www.maxpronko.com

Page 26: Real use cases of performance optimization in magento 2

REMOVE BLOCKS FROM LAYOUT

➤ Debug Hints

➤ Find non-used Blocks

➤ Remove it

www.maxpronko.com

Page 27: Real use cases of performance optimization in magento 2

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

Page 28: Real use cases of performance optimization in magento 2

HOW ABOUT BLOCK CACHE?

www.maxpronko.com

Page 29: Real use cases of performance optimization in magento 2

BLOCK CACHE

➤ Reduce number of Database queries

➤ Collection Load

➤ Template processing

➤ Eliminate Inline Translation

www.maxpronko.com

Page 30: Real use cases of performance optimization in magento 2

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

Page 31: Real use cases of performance optimization in magento 2

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

Page 32: Real use cases of performance optimization in magento 2

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

Page 33: Real use cases of performance optimization in magento 2

CATEGORY PAGE

www.maxpronko.com

Page 34: Real use cases of performance optimization in magento 2

CACHED BLOCKS

Navigation

Product

Price

www.maxpronko.com

Page 35: Real use cases of performance optimization in magento 2

BreadcrumbLayered

Navigation

Product

Product List

NON-CACHED BLOCKS

www.maxpronko.com

Page 36: Real use cases of performance optimization in magento 2

LETS USE BLOCK CACHE

www.maxpronko.com

Page 37: Real use cases of performance optimization in magento 2

BREADCRUMBS BLOCK

default.xml

<referenceBlock name="breadcrumbs"> <arguments> <argument name="cache_lifetime" xsi:type="string">604800</argument> </arguments> </referenceBlock>

www.maxpronko.com

Page 38: Real use cases of performance optimization in magento 2

LAYERED NAVIGATION BLOCK

➤ Layer State Key

➤ Category

➤ Customer Group

➤ Store

➤ Filters

➤ Currency

www.maxpronko.com

Page 39: Real use cases of performance optimization in magento 2

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

Page 40: Real use cases of performance optimization in magento 2

LAYERED NAVIGATION PLUGIN DECLARATION

di.xml<config> <type name="Magento\LayeredNavigation\Block\Navigation"> <plugin name="LayeredNavigationCacheKey" type="Pronko\Performance\Plugin\LayeredNavigationPlugin"/> </type> <type name="Magento\LayeredNavigation\Block\Navigation\Category"> <plugin name="LayeredNavigationCacheKey" type="Pronko\Performance\Plugin\LayeredNavigationPlugin"/> </type> </config>

www.maxpronko.com

Page 41: Real use cases of performance optimization in magento 2

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

Page 42: Real use cases of performance optimization in magento 2

PRODUCT LIST<?php$_productCollection = $block->getLoadedProductCollection();$_helper = $this->helper('Magento\Catalog\Helper\Output');?> <?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 = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW; } else { $viewMode = 'list'; $image = 'category_page_list'; $showDescription = true; $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::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 \Magento\Catalog\Model\Product */ ?> <?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('Magento\Wishlist\Helper\Data')->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('Magento\Catalog\Helper\Product\Compare'); ?> <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> </div>

Page 43: Real use cases of performance optimization in magento 2

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

Page 44: Real use cases of performance optimization in magento 2

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 */ echo $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

Page 45: Real use cases of performance optimization in magento 2

CATEGORY PAGE - CACHED

www.maxpronko.com

Page 46: Real use cases of performance optimization in magento 2

RELATED PRODUCTSProduct Page

www.maxpronko.com

Page 47: Real use cases of performance optimization in magento 2

PRODUCT PAGE

www.maxpronko.com

33 Attributes EAV Tables

Page 48: Real use cases of performance optimization in magento 2

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

Page 49: Real use cases of performance optimization in magento 2

ATTRIBUTES CONFIG

namespace Magento\Catalog\Model;class Config extends \Magento\Eav\Model\Config{ public function getProductAttributes(){ if (is_null($this->_productAttributes)) { $this->_productAttributes = array_keys($this->getAttributesUsedInProductListing()); } return $this->_productAttributes; }

}

Page 50: Real use cases of performance optimization in magento 2

ATTRIBUTES CONFIG

namespace Pronko\Performance\Model\Config;class Related extends \Magento\Catalog\Model\Config{ 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)); }}

Page 51: Real use cases of performance optimization in magento 2

CONFIGURATION

<virtualType name="PronkoPerformanceProductRelatedContext" type="Magento\Catalog\Block\Product\Context"> <arguments> <argument name="catalogConfig" xsi:type="object">Pronko\Performance\Model\Config\Related</argument> </arguments> </virtualType> <type name="Pronko\Performance\Block\ProductList\Related"> <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

Page 52: Real use cases of performance optimization in magento 2

CATALOG_PRODUCT_VIEW.XML

<referenceBlock name="catalog.product.related" remove="true" />

<referenceContainer name="content.aside"> <block class="Pronko\Performance\Block\ProductList\Related" name="pronko.catalog.product.related" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">related</argument> </arguments> </block> </referenceContainer>

Page 53: Real use cases of performance optimization in magento 2

3RD PARTY MODULES

www.maxpronko.com

Page 54: Real use cases of performance optimization in magento 2

DOUBLE CHECK

➤ HTTP POST requests

➤ Collections usage

➤ Slow file/database operations

➤ Performance Tests on staging server

www.maxpronko.com

Page 55: Real use cases of performance optimization in magento 2

VARNISH

www.maxpronko.com

Page 56: Real use cases of performance optimization in magento 2

X-MAGENTO-VARY

➤ Customer Logged In

➤ Customer Group

➤ Customer Segment (EE only)

➤ Store

➤ Currency

➤ Tax Rates

www.maxpronko.com

Page 57: Real use cases of performance optimization in magento 2

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

Page 58: Real use cases of performance optimization in magento 2

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

Page 59: Real use cases of performance optimization in magento 2

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

Page 60: Real use cases of performance optimization in magento 2

WHAT ELSE?

www.maxpronko.com

Page 61: Real use cases of performance optimization in magento 2

MORE PERFORMANCE OPTIMISATIONS

➤ Remove Compare Products feature

➤ Minify and merge JavaScript and CSS

➤ Enable Async Order Grid

➤ Enable Async Transactional Emails

www.maxpronko.com

Page 62: Real use cases of performance optimization in magento 2

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

Page 63: Real use cases of performance optimization in magento 2

PERFORMANCE TOOLS

www.maxpronko.com

Page 64: Real use cases of performance optimization in magento 2

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

Page 65: Real use cases of performance optimization in magento 2

THANK YOUmax_pronko

Q&A Time

www.maxpronko.com