{"id":45606,"date":"2017-02-08T15:37:00","date_gmt":"2017-02-08T10:07:00","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=45606"},"modified":"2017-05-01T15:35:09","modified_gmt":"2017-05-01T10:05:09","slug":"best-practices-to-optimize-performance-in-drupal-8","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/best-practices-to-optimize-performance-in-drupal-8\/","title":{"rendered":"Best Practices to Optimize Performance in Drupal 8"},"content":{"rendered":"<p><span style=\"font-weight: 400;\"><strong>Drupal<\/strong>, a content management system has the\u00a0capability to serve large data in different formats based on business need. A business requirement could be a data exchange between two web properties or sourcing a data or consuming data from external sources. Also, <a title=\"Drupal development\" href=\"http:\/\/www.tothenew.com\/wcm\/drupal-development-consulting-services\">Drupal<\/a>\u00a0is gaining confidence\u00a0in today\u2019s market and also widely being used as SAAS. Now questions raised by big organizations before adopting Drupal is about its ability in terms of functionalities, features, compatibility, flexibility and most important performance.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Performance is a\u00a0most crucial piece in any web\/desktop application. It can truly turn down the market of any application. For example: A chariot can comfortably pull 3 men with two horses however if few more people board the same chariot, it will either not work or the speed will be reduced. This is simply because you are running a chariot with a wrong infrastructure and the same analogy holds true in the\u00a0case of a web\/desktop application.\u00a0There&#8217;s\u00a0<\/span>no disclaimer with an application like it will perform with only a specific kind of infrastructure or it will serve the content to only specific concurrent users or about the page load time. And there are no benchmarks given on any of the competitive portals like WordPress , Joomla or other CMS.<\/p>\n<p>The intent to write this blog is to help you think in a different direction, i.e. if a\u00a0site is not performing well as expected then it is imperative to understand the underlying issue and find an appropriate solution to optimize the performance rather than blaming the capabilities of the CMS. I will provide few insights of <a title=\"Advantages of Drupal 8\" href=\"http:\/\/www.tothenew.com\/blog\/advantages-of-drupal-8-over-other-cms\/\">Drupal 8<\/a>. Drupal 8 is new, elegant and more promising as compared to its earlier versions 6\/7. \u00a0The process to improve performance can be almost similar in all the versions, but unless you have some in-depth understanding you will not be able to handle critical situations.<\/p>\n<p>Outlined below are few key points to keep in mind for performance optimization.<\/p>\n<p>1)<b>\u00a0<\/b><span style=\"font-weight: 400;\">\u201c<\/span><b>Avoid any manual configuration of standard settings as application core code changes over time.<\/b><span style=\"font-weight: 400;\">\u201d Drupal community keeps a track of performance loose poles and detects Drupal application components and dependencies and optimize it in every new core updates.<\/span><\/p>\n<p>Drupal 8 started with merging 100s of contributed modules in it. This gives a strong backend and flexibility to handle complex data structure. Merging these modules in core isn&#8217;t easy as these modules are ported from Drupal 7 to Drupal 8 and then are merged. Stability of these ported\/merged module was hindering at an early age of Drupal 8 in 2016 but now it has become quite stable. To stablize these ported core modules in projects; the developers have modified codes which does not follow the Drupal\/Symfony standard and can impact the performance.<\/p>\n<p>2)<span style=\"font-weight: 400;\">\u00a0\u201c<\/span><b>List valuable transactions for monitoring in order to optimize performance<\/b><span style=\"font-weight: 400;\">\u201d. We should not get bog down to unnecessary smaller operations instead should focus on critical operations of the site or the area where user hits are atmost. Basically this requires understanding of client-side performance impact which correlates to browser and device performance to originating site performance metrics.<\/span><\/p>\n<p>Drupal 8 deployment requires an adequate cache strategy which should minimize database interactions before we actually see the database load on the server. Areas below must be overlooked before originating performance metrics :<\/p>\n<ul>\n<li style=\"font-weight: 400;\"><b>Server Cache<\/b><span style=\"font-weight: 400;\"> (Varnish \/ CloudFront) : Verify anonymous user pages cached. This can be verified by checking log or URL header i.e. URL header should not have <strong>no-cache<\/strong>\u00a0in Cache-Control.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span><b>Linux Command<\/b><\/p>\n<pre> $ curl -I http:\/\/www.yoursite.com \r\nAccept-Ranges: bytes\r\nAge: 0\r\nCache-Control: must-revalidate, <strong>no-cache<\/strong>, private\r\nContent-language: en\r\nContent-Type: text\/html; charset=UTF-8\r\nServer: nginx\r\nStrict-Transport-Security: max-age=31536000\r\nVary: Accept-Encoding\r\nVia: 1.1 varnish\r\nX-AH-Environment: prod\r\nX-Cache: MISS\r\nX-Content-Type-Options: nosniff\r\nX-Frame-Options: SAMEORIGIN\r\nX-Generator: Drupal 8 (https:\/\/www.drupal.org)\r\nX-Request-ID: v-bdcbc8d4-d269-11e6-b0bd-0efda0c0bb84\r\nX-UA-Compatible: IE=edge\r\nX-Varnish: 1350530508\r\nContent-Length: 76311\r\nConnection: keep-alive\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\"><b>Page Cache<\/b><span style=\"font-weight: 400;\"> (<\/span><span style=\"font-weight: 400;\">http:\/\/www.yoursite.com\/admin\/config\/development\/performance<\/span><span style=\"font-weight: 400;\">) : Ideally it should be 6 hours but it depends on busniess requirement.<\/span><\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-45613\" src=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/page-cache1-300x48.png\" alt=\"page-cache\" width=\"300\" height=\"48\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/page-cache1-300x48.png 300w, \/blog\/wp-ttn-blog\/uploads\/2017\/01\/page-cache1-624x100.png 624w, \/blog\/wp-ttn-blog\/uploads\/2017\/01\/page-cache1.png 815w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><b>View \/ Block Cache<\/b><span style=\"font-weight: 400;\"> : While creating a view we should set caching based on its behavior. View add\/edit pages has (advance -&gt; other -&gt; caching) section which provides flexibility to set caching based on following :<\/span>\n<ul>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">None : No cache required<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Tag Based : Cache view\/block based on URL<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Time Based : Cache view\/block based on following timing :<\/span>\n<ul>\n<li style=\"font-weight: 400;\"><b>Query results : <\/b><span style=\"font-weight: 400;\">The length of time raw query results should be cached.<\/span><\/li>\n<li style=\"font-weight: 400;\"><b>Rendered : <\/b><span style=\"font-weight: 400;\">The length of time rendered HTML output should be cached.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-45616\" src=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/image00-300x172.png\" alt=\"image00\" width=\"300\" height=\"172\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/image00-300x172.png 300w, \/blog\/wp-ttn-blog\/uploads\/2017\/01\/image00.png 387w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Best approach for View caching is a tag based caching. <\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><b>Custom Block Cache<\/b><span style=\"font-weight: 400;\">: While creating a custom block we can also define cache in return parameters like below :<\/span><\/li>\n<\/ul>\n<pre>return array(\r\n      '#theme' =&gt; \u201cnew_theme\u201d,\r\n      '#var1' =&gt; $var1,\r\n      '#var2' =&gt; $var2,\r\n      '#cache' =&gt; ['contexts' =&gt; ['url.path'] ],\r\n    );\r\n<\/pre>\n<p><span style=\"font-weight: 400;\">Best approach for setting cache is based on contexts. You can find more cache contexts on <\/span><a href=\"https:\/\/www.drupal.org\/docs\/8\/api\/cache-api\/cache-contexts\"><span style=\"font-weight: 400;\">https:\/\/www.drupal.org\/docs\/8\/api\/cache-api\/cache-contexts<\/span><\/a><span style=\"font-weight: 400;\"> page. <\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">You can also define time based caching by specify max-age.<\/span><\/li>\n<\/ul>\n<pre>return array(\r\n      '#theme' =&gt; \u201cnew_theme\u201d,\r\n      '#var1' =&gt; $var1,\r\n      '#var2' =&gt; $var2,\r\n      '#cache' =&gt; ['max-age' =&gt; 360 ],  \/\/ Set 0 for no-caching\r\n    );\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\"><b>Data structure\/Query Caching <\/b><span style=\"font-weight: 400;\">: Data structure caching reduces significant amount of \u00a0database interaction and serves data directly to front-end. Following tool will be helpful regarding the same:<\/span>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Redis<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Memcache<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Here I would like to advocate Redis which is being widely used right now. Following configuration in settings.php to enable Redis cache. (Must have Redis server and module installed)<\/span><\/p>\n<pre>    # Use for all bins otherwise specified.\r\n    $settings['cache']['default'] = 'cache.backend.redis';\r\n  \r\n    # Use this to only use it for specific cache bins.\r\n    $settings['cache']['bins']['render'] = 'cache.backend.redis';\r\n\r\n<\/pre>\n<p>3)<b> <\/b><span style=\"font-weight: 400;\">\u201c<\/span><b>Keep track of errors and exceptions originated from PHP<\/b><span style=\"font-weight: 400;\">\u201d. Enable database logging and keep watching any warnings, exceptions and notices. If we reduce these errors it will improve PHP execution time and hence give positive impact on overall site performance.<\/span><\/p>\n<p>4) <span style=\"font-weight: 400;\">\u201c<\/span><b>Keep HTML skeleton as simple as possible<\/b><span style=\"font-weight: 400;\">\u201d. Drupal provides its own basic themes to start with. While creating new theme usually front-end developers simply overrides the required templates such as home page layout or node page and for rest of the pages they override CSS. This approach is fine for rapid development but then it adds a lot of unwanted layers in the HTML. For example :<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-45614\" src=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/image01-300x266.png\" alt=\"image01\" width=\"300\" height=\"266\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2017\/01\/image01-300x266.png 300w, \/blog\/wp-ttn-blog\/uploads\/2017\/01\/image01.png 372w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">A particular field item will be rendered under 5-6 layers. Ideally we should remove view, block and some other unwanted layer so that HTML output should be as simple as required. Default Drupal theme also tried to use semantic tags for node (&lt;article&gt;) and tried to wrap all the item under the same tag. Here we need improvement as page should be divided in different sections. See the link http:\/\/www.w3schools.com\/html\/html5_semantic_elements.asp for better understanding of \u00a0HTML5 tags.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Drupal, a content management system has the\u00a0capability to serve large data in different formats based on business need. A business requirement could be a data exchange between two web properties or sourcing a data or consuming data from external sources. Also, Drupal\u00a0is gaining confidence\u00a0in today\u2019s market and also widely being used as SAAS. Now questions [&hellip;]<\/p>\n","protected":false},"author":910,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":7},"categories":[3602],"tags":[4407,4405,857,4408,4406],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/45606"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/910"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=45606"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/45606\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=45606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=45606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=45606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}