Drupal Performance: Eliminating the Render-Blocking resources
We should be able to make some significant improvements here for very little effort.
Move Scripts to the Bottom of the Page
<html> <head> ... <?php print $head_scripts; ?> </head> <body class="<?php print $classes; ?>" <?php print attributes; ?>> ... <?php print $scripts; ?> </body> </html>
Since I already am limiting how many scripts are in my Document head, let's move on to other improvements.
Eliminate Unnnecessary Legacy Libraries
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load */
Ok, based on that I can see it’s a bunch of standard CSS feature checks for gradients, transforms, rounded corners, the usual lot of stuff that didn’t work until IE9 and IE10. Let me check my theme’s JS….. nope, nothing there that depends on anything from Modernizer. How about my theme’s CSS? Again, nothing that is depending on the classes that Modernizer generates. All this time this has been loading on my pages, wasting CPU performance. I probably had it because I followed the HTML 5 boilerplate defaults, or perhaps I was doing some transparency and rounded corners support in IE8. Regardless, it’s certainly unnecessary now, let’s remove it by deleting modernizr-2.6.2.min.js from my theme folder and also commenting out the lines in my template preprocess html hook that were adding it to the document head script array:
$path = drupal_get_path('theme', 'amc'); drupal_add_js($path . '/js/vendor/modernizr-2.6.2.min.js', array('scope' => 'head_scripts', 'weight' => -1, 'preprocess' => FALSE));
Let’s see what that does for the performance:
Specify media types for CSS links
But here’s something interesting in how Lighthouse identifies render-blocking CSS:
Does not have a media attribute that matches the user's device.
Ahah! The stylesheets are linked with the attribute media=“all” which means both the print and screen styles are loaded all the time. By being more specific with the media attribute on the <llink> tags, the styleshseets will no longer be render-blocking. I can easily clean this up by making some small changes to the theme's .info file:
stylesheets[all] = css/normalize.css stylesheets[all] = css/main.css stylesheets[all] = css/base.css stylesheets[all] = css/skeleton.css stylesheets[all] = css/menu.css stylesheets[all] = css/portfolio.css
Changing these from media “all” to media “screen” should help. Also, I have all my print styles wrapped in one print media query in main.css, so I’ll move those to a new file called print.css and update the theme .info file accordingly:
stylesheets[screen] = css/normalize.css stylesheets[screen] = css/main.css stylesheets[screen] = css/base.css stylesheets[screen] = css/skeleton.css stylesheets[screen] = css/menu.css stylesheets[screen] = css/portfolio.css stylesheets[print] = css/print.css
There’s also one CSS file loaded remotely from Google Fonts. That one isn’t in the theme .info file, instead it’s being added via PHP, so I need to address it there so that it also is set with the media type. This one is the web fonts, which are needed both for screen and print, so I'll set the media type accordingly when I add it to Drupal's list of CSS files for the page:
//Add fonts from Google CDN drupal_add_css('http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,400italic|Open+Sans:300', array('type' => 'external'));
//Add fonts from Google CDN drupal_add_css( 'http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,400italic|Open+Sans:300', array( 'type' => 'external', 'media' => 'screen or print' ) );
Aggregating CSS and JS
There is a Drupal module for Advanced CS/JSS Aggregation which provides more granular controls and aggressive caching mechanisms than the out-of-box concatenation and caching. Install it via the modules manager, and then enable it:
Then in the configuration for the module, let's enable some features:
- Use Customized Settings - Since my site isn't HTTP2, I want to get more fine grained than the defaults
- Bundler is Active - Enable this, or else why even both installing the module?
- Target Number Of CSS Bundles Per Page - Since I don't have a lot of blocks or other reusable elements, I can get away with very few generated files. I set this to 2. The lower it is set, the better the initial page load performance will be, but the higher the likelyhood that visitors will need to download page-specific files as they navigate across multiple pages of your site.
As usual, flush all the caches, and let's run the Lighthouse audit again:
Set the configuration for each. For the CSS compression module I want:
- Compressor: Core - I don't want to use YUI because I don't want to download the library, and because it is an ancient compressor that's buggy with modern files.
- Inline Compression: Disabled
For the JS compression module I want:
- Compressor: JSqueeze - This is the fastest that doesn't require reconfiguring the server
- Inline Compressor: JSQueeze
There's a bunch more options in the main module if you choose "Use Customized Settings", but those may impact site behavior, so I'll go through them later with more granularity when I can test specific outcomes. In the meantime, just these basic straightforward settings have made significant performance improvements to this Drupal site.