Site icon Haktan Suren, PhD

How I got a perfect score on Google’s PageSpeed Insights

Today, I am going to show you how i took a website having 47 Google’s PageSpeed Insights score and make it up to 98. Yes, you heard me right, ninety friggin eight almost full score! Now, I will share all the details so you can just do it without spending hours, yes literally hours unlike me.

First let me tell you about my server specs. I am hosting my website on Amazon (AWS) EC2 and I have Red Hat 4.8.3-9 operating system installed with Apache/2.4.23. All right, ready to go? Let’s the show begin…

Optimize Images (Image Compression)

First I have optimized all the images on my server. In order to save from disk space as well as the bandwidth, it is a perfect candidate to start with. To do that, I have used two different image optimization executable on Linux that allows lossless compression (file size reduction). The first one is optipng and the other is jpegoptim

find -name '*.png' -print0 | xargs -0 optipng -nc -nb -o7

The above code recursively traverse your current directory and find all the PNG files and makes sure no color / brightness / saturation changes using the best compression algorithm. You have to be careful using this, because it is not reversible, in other words, it overwrites the images.

Let’s do this for all the JPG files now similarly…

find . -name "*.jpg" | xargs jpegoptim 

All done… As far as I know both tools allow preserving original images using a flag. I will let you discover that…

Leverage browser caching

Next is adding caching headers to your files so that browsers can cache your content client-side. In order to do that, I have created a configuration file under /etc/httpd/conf.d/perf.conf so that Apache can read. And then inserted the following lines. Do not forget the location of this file, we will come back and add some more stuff soon.

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>

Basically, it is to tell Apache to add `Cache-Control` line in the header of the files. You can define any duration (period) you want specific to each file type as shown above.

Minify JavaScript, Minify CSS and Minify HTML

Remember I told you, do not forget the location of the configuration file? It is time to re-visit that file for minifying JS, CSS and HTML.

So, I have two piece of code for this section, the first one is to prevent double gzip (compression) and only provide the gzip version of the file if/when client browser supports it and serving gzip compressed CSS and JS file if they are available on the server. Believe me, it is a TON of a bandwidth saving.

<IfModule mod_headers.c>
    # Serve gzip compressed CSS files if they exist
    # and the client accepts gzip.
    RewriteCond "%{HTTP:Accept-encoding}" "gzip"
    RewriteCond "%{REQUEST_FILENAME}\.gz" -s
    RewriteRule "^(.*)\.css" "$1\.css\.gz" [QSA]

    # Serve gzip compressed JS files if they exist
    # and the client accepts gzip.
    RewriteCond "%{HTTP:Accept-encoding}" "gzip"
    RewriteCond "%{REQUEST_FILENAME}\.gz" -s
    RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]


    # Serve correct content types, and prevent mod_deflate double gzip.
    RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
    RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1]


    <FilesMatch "(\.js\.gz|\.css\.gz)$">
      # Serve correct encoding type.
      Header append Content-Encoding gzip

      # Force proxies to cache gzipped &
      # non-gzipped css/js files separately.
      Header append Vary Accept-Encoding
    </FilesMatch>
</IfModule>

The second bit of code is to compress all the files ending with .js, .css and .html.

<filesMatch "\.(js|html|css)$">
    SetOutputFilter DEFLATE
</filesMatch>

Eliminate render-blocking JavaScript and CSS

This is the killer. We will use Google’s ModPageSpeed module to take care of everything that makes rendering slow. Some people say ModPageSpeed is just enough it is own to boost up the performance 50% or more. OK, here is the code.

ModPageSpeed on
ModPagespeedRewriteLevel CoreFilters
ModPagespeedEnableFilters prioritize_critical_css
ModPagespeedEnableFilters defer_javascript
ModPagespeedEnableFilters sprite_images
ModPagespeedEnableFilters convert_png_to_jpeg,convert_jpeg_to_webp
ModPagespeedEnableFilters collapse_whitespace,remove_comments
ModPagespeedEnableFilters make_google_analytics_async
ModPagespeedEnableFilters inline_google_font_css

In case you do not have ModPageSpeed installed on your server, you can simply download and install it here. It is plug-n-play, after installing it, it will be configured automatically.

If you have come to this point, I can guarantee that you have already boosted up the performance 75% more. Let me know how it did for you by commenting below. I read and reply ALL the comments.

Exit mobile version