Mittul At TechnoBrave
Mittul At TechnoBrave

Reputation: 1242

Serve static assets with an efficient cache policy - Google PageSpeed Insights

I am using OctoberCMS and I have apache server and using AWS and when I do PageSpeed testing https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.rosterelf.com%2F&tab=desktop I am keep getting this errror saying

Serve static assets with an efficient cache policy

Here is my .htaccess file code to counter this error.

.htaccess

<IfModule mod_rewrite.c>

    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    <IfModule mod_headers.c>
        <If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">            
            Header always set Strict-Transport-Security "max-age=31536000"
        </If>
    </IfModule>

 

    ### MY OTHER DEFAULT CODE OF OCTOBERCMS WHICH IS NOT RELATED TO COMPRESSION ETC ... 

</IfModule>


# TN START GZIP COMPRESSION
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
# TN END GZIP COMPRESSION

# TN START DEFLATE COMPRESSION
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font" \
"application/x-font-opentype" \
"application/x-font-otf" \
"application/x-font-truetype" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/otf" \
"font/ttf" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
# END DEFLATE COMPRESSION

# TN START ENABLE KEEP ALIVE
<ifModule mod_headers.c>
Header set Connection keep-alive

# WEEK
<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=604800, public"
</FilesMatch>

# WEEK
<FilesMatch "\.(js|css|swf)$">
    Header set Cache-Control "max-age=604800"
</FilesMatch>

</ifModule>
# TN END ENABLE KEEP ALIVE

# TN - START EXPIRES CACHING #
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/x-icon "access 1 year"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/svg "access 1 year"
ExpiresByType audio/ogg "access plus 1 year"
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/mpeg "access plus 1 year"
ExpiresByType video/ogg "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/pdf "access 1 month"
ExpiresByType application/javascript "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/xhtml-xml "access 1 month"
ExpiresByType text/x-component "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 year"

# Fonts
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"

ExpiresDefault "access 1 month"
</IfModule>
# TN - END EXPIRES CACHING #

But still its keeping this error with 77 resources.

I have tried many things as you can see by adding so much code but yet error count not reducing and its keep getting .js, .png, .css files as well.

Can someone guide me what I am missing here in my code.

Thanks


Updated HTACCESS FILE

<IfModule mod_rewrite.c>

    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    <IfModule mod_headers.c>
        <If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">            
            Header always set Strict-Transport-Security "max-age=31536000"
        </If>
    </IfModule>

    RewriteEngine On

    ##
    ## You may need to uncomment the following line for some hosting environments,
    ## if you have installed to a subdirectory, enter the name here also.
    ##
    # RewriteBase /   


</IfModule>


# TN START GZIP COMPRESSION
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
# TN END GZIP COMPRESSION

# TN START DEFLATE COMPRESSION
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font" \
"application/x-font-opentype" \
"application/x-font-otf" \
"application/x-font-truetype" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/otf" \
"font/ttf" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
# END DEFLATE COMPRESSION

# TN START ENABLE KEEP ALIVE
<IfModule mod_headers.c>
    Header set Connection keep-alive

</IfModule>
# TN END ENABLE KEEP ALIVE

# TN - START EXPIRES CACHING #
<IfModule mod_expires.c>
ExpiresActive On

ExpiresDefault "access plus 1 month"

ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/html "access plus 1 month"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/svg "access plus 1 year"
ExpiresByType audio/ogg "access plus 1 year"
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/mpeg "access plus 1 year"
ExpiresByType video/ogg "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/xhtml-xml "access plus 1 month"
ExpiresByType text/x-component "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 year"

# Fonts
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"

  <IfModule mod_headers.c>
          Header append Cache-Control "public"
  </IfModule>


</IfModule>


<IfModule mod_headers.c>
  Header unset ETag
</IfModule>
FileETag None

<IfModule mod_headers.c>
  Header unset Last-Modified
</IfModule>

# TN - END EXPIRES CACHING #

Upvotes: 9

Views: 20469

Answers (2)

Chris Ahrweiler
Chris Ahrweiler

Reputation: 1

Google does not say what expires time they expect. I have testet with different value and it looks like 4 month = 10368000 is ok. So this is the settin I use:

<IfModule mod_headers.c>
    Header set Connection keep-alive
    <filesmatch "\.(ico|ttf|woff|woff2|pdf|webm|mp[\d]+)$">
        # 4 month
        Header set Cache-Control "max-age=10368000, public"
    </filesmatch>
    <filesmatch "\.(gif|jpe?g|png|svg|webp)$">
        Header set Cache-Control "max-age=10368000, public"
    </filesmatch>
    <filesmatch "\.(css|js|xsl)$">
        # 30 days
        Header set Cache-Control "max-age=2592000, private"
    </filesmatch>
    <filesMatch "\.(x?html?|xml|txt|php)$">
        Header set Cache-Control "max-age=600, private, must-revalidate"
      </filesMatch>
</IfModule>

Upvotes: 0

MrWhite
MrWhite

Reputation: 46012

But still its keeping this error with 77 resources.

Bear in mind that some of these resources are on external domains for which you have no control.

As stated in the linked document from the PageSpeed results:

When possible, cache immutable static assets for a long time, such as a year or longer.

For one of your .jpg resources .../images/rosterelftechsupport.jpg which is reported by Google's pagespeed insights as being cached for "30 d" it has the following HTTP response headers:

cache-control: max-age=2592000, public
expires: Thu, 12 May 2022 16:05:33 GMT

Whilst the expires header states a cache time of 1 year, the max-age directive of the cache-control header states 30 days (2,592,000 seconds). All modern browsers will prioritise the cache-control: max-age header, so "30 days" is the cache time.

ExpiresByType image/jpeg "access 1 year"

This mod_expires directive sets both the expires and the cache-control: max-age headers on .jpg (mime-type: image/jpeg) files. So, this does seem to be honoured, since the expires header is set correctly and you aren't explicitly setting this anywhere else.

<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=604800, public"
</FilesMatch>

However, any Header set Cache-Control (mod_headers) directive, such as this, will override the Cache-Control header set by mod_expires and affect the cache time. So, it would seem you may still have a rogue Header directive?

You certainly don't need both. If you are using mod_expires then only use mod_expires. You do not need mod_headers for this. In other words, you should remove all <FilesMatch ...> Header set Cache-Control ... </FilesMatch> blocks (such as that above) since they are directly conflicting with the mod_expires directives (ie. ExpiresByType).

The only reason to use a mod_headers Header set Cache-Control ... directive is if mod_expires was not available on your server. The only reason to use both mod_expires and mod_headers here is if you are installing your application on multiple servers and it is expected that mod_expires is not installed on all servers (unlikely). In which case, the mod_headers directives should be enclosed inside a <IfModule !mod_expires.c> container (ie. "if mod_expires is not available"), otherwise mod_headers will always take priority (as mentioned above).

You need to make sure the browser and any intermediary proxy caches are clear before testing, since this resource has been cached for "30 days".


UPDATE:

I have removed FilesMatch from file and also checked in my "Private Window" of my browser and opened the website and then ran the "Pagespeed Insights" .. but its still showing around 56 resources not cached including png images etc.

All the .jpg and .png images served from your domain are no longer present in that report, so they would seem to be "resolved".

The remaining 8 .png images that are still showing in the report and have no Cache-Control or Expires headers are being served directly from s3-ap-southeast-2.amazonaws.com - which your directives are not necessarily going to influence. You may need to check the settings on your S3 bucket?

...config/176…?v=2.9.39&r=stable(connect.facebook.net)        20m

You have 7 resources served from external 3rd parties (such as this) which you have no control over.

...industries/nonprofit.svg(www.rosterelf.com)                30 d

ExpiresByType image/svg+xml "access plus 1 month"

You have 22 .svg images served from your domain. These are all served with a image/svg+xml content-type. As you can see from the above ExpiresByType directive these are "only" set to be cached for a period of "1 month" (ie. 30 days). If you want these to be cached for a longer period then change the above directive as you have already done for JPEG and PNG files.

...js/swiper-bundle.min.js(www.rosterelf.com)                 30 d

ExpiresByType application/javascript "access plus 1 month"

You have 11 .js files served from your domain - all served with an application/javascript content-type. Change the above ExpiresByType directive accordingly if you want these files to be cached for longer.

HOWEVER, you should note that Google's PageSpeed report is only a "suggestion". Only change this (and other caching directives) if it makes sense for your system. You will have issues if these files need to be changed before the cache expires unless you have implemented some other cache-busting technique.

This also means that the following directives are entirely superfluous and can be removed:

ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"

Your server is sending .js responses with the correct application/javascript mime-type, so setting caching directives for text/javascript and text/x-javascript as well is not required.

...css/custom.min.css(www.rosterelf.com)                     30 d

ExpiresByType text/css "access plus 1 month"

You have 6 .css files served from your domain. The same applies above as for .js files.

... fonts/social-media-icon.ttf?lvmhu5(www.rosterelf.com)    30 d

You have 6 .ttf (font) files. Yes, these should certainly be cached for a longer period. These are all served with an application/font-sfnt*1 mime/content-type. However, you do not explicitly have a directive that covers this, so it will default to the ExpiresDefault (ie. 1 month). You need to add the appropriate directive for this mime-type. For example:

ExpiresByType application/font-sfnt "access plus 1 year"

(*1 application/font-sfnt is actually deprecated in favour of font/sfnt.)

This might mean that all the following (font-caching) directives are superfluous, if you are not serving these file-types?

ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 year"

# Fonts
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"

And to emphasise my comment above... the results from Google's PageSpeed report (and any other SEO report) are only advisory... a possible suggestion. It is not necessarily "wrong" to serve resources with a shorter cache time. These "suggestions" are not meant to be followed blindly. Do not implement long cache times to simply satisfy the report. Only if it makes sense to your application should these resources be cached for longer periods.

Upvotes: 3

Related Questions