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

2

8

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 #
Darfur answered 30/4, 2021 at 5:52 Comment(10)
Just the length of cache - they expect 6 months minimum and ideally 1 year for all static assets. So just increase your cache times on them (CSS, JS, SVG look to be the only ones to bother about) and employ cache busting techniques if they change. I can't see anything else from the file given.Hoicks
@GrahamRitchie Thanks for your reply and your feedback. So Do I need to change all to set as "1 month" ?Darfur
Change all the "1 month" to at least 6 month or preferably a year. But that is only for static assets (so HTML can be shorter, rss can be shorter etc.). Think of static assets as anything that sits in the file system rather than getting generated via code - all of these should have 1 year caches.Hoicks
You also have a few duplicates - e.g. <FilesMatch "\.(js|css|swf)$"> so you may want to remove that as you set them all further down and so they should be overridden.Hoicks
hmm, seems from your site response your images do not have any cache thing, make sure your mod_headers is enabledSalchunas
@GrahamRitchie I have removed dulicates as you mentioned .. can you please specify which of the items from the list i should set as 1 year ?Darfur
@GrahamRitchie Also can you suggest anything else why I am keep getting around 77 files having images, png etc .. I have already put a call in my htaccess file.Darfur
whatever you have done isn't quite right. Inspecting the headers the expires is set to 1 month still. Remove the <FilesMatch "\.(js|css|swf)$"> part it is obviously taking priority,Hoicks
I have removed the files match .. do I need to do anything else apart from expiry time ?Darfur
@HardikSatasiya Thanks bro for your inputs. I have checked and mod_headers are already enabled as I am using AWS server .. What other things I can do to remove the errors related to png images and other issues for the same error ? Can you please guide me?Darfur
S
3

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.

Systematic answered 13/5, 2021 at 0:37 Comment(9)
Thanks for your answer .. so do you believe I should remove <FilesMatch "\.(jpg|jpeg|png|gif|swf)$"> from my code ? Can you please help me .. I am totally blank on this. ThanksDarfur
@MittulAtTechnoBrave Yes, you should remove all <FilesMatch ...> Header set Cache-Control ... </FilesMatch> blocks since they are directly conflicting with the mod_expires directives (ie. ExpiresByType). I've updated my answer to clarify this.Systematic
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.Darfur
I have also updated .htaccess file in my question so you can have better what's inside the file now.Darfur
I have also removed Header unset ETag part, Header unset Last-Modified part, from the htaccess file but still its showing same caching errors.Darfur
@MittulAtTechnoBrave "but its still showing around 56 resources not cached including png images etc." - those remaining PNG images are on a different domain and may be out of your control (or configurable from your S3 bucket?). I've updated my answer to address this and other file types appearing in that report.Systematic
Thanks for feedback. I have removed ExpiresByType text/javascript "access plus 1 month", ExpiresByType text/x-javascript "access plus 1 month",ExpiresByType text/css "access plus 1 month" and added ExpiresByType application/font-sfnt "access plus 1 year" as per your feedback and suggestion. Seems like it has reduced the number. But I am still have png and svg errors of images which are in my control. Can you suggest me what is the cause now ? ThanksDarfur
@MittulAtTechnoBrave I did not say to remove ExpiresByType text/css "access plus 1 month" - that needs to be updated (like JS files) if you want a longer cache time on your CSS files (but note the caveats as mentioned). The PNG images listed do not reference your domain? And I covered SVG images in my answer above already.Systematic
I am OK with the caching time of 1 month for css and js files. Yes, few of the PNG files are getting served from S3 bucket. what should I do for them ?Darfur
A
0

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>
Ansley answered 19/6, 2024 at 8:9 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.