I have a site.webmanifest file that was added when I created favicons for a website. A check on webpagetest.org said: FAILED (No max-age or expires): https://[my-site]/site.webmanifest

Having done some research I thought that the site.webmanifest file was a kind of json file so I added this to the .htaccess file: ExpiresByType application/json “access plus 1 year”

But I still got the same fail message, so I tried

ExpiresByType application/webmanifest “access plus 1 year”

and ExpiresByType application/site.webmanifest “access plus 1 year”

and ExpiresByType text/site.webmanifest “access plus 1 year” in case it's not an application, and

ExpiresByType manifest/site.webmanifest “access plus 1 year”

with again, the fail message. [I asked this question back in January 2023 on forum.joomla.org without any response, so I'm trying here].

From what I understand, this file tells Android devices about the icon that can be added to a home screen for a quick link to the website. But maybe it doesn't apply to websites, only Apps. I haven't built any apps, only Joomla websites, so maybe I don't need this file at all?

UPDATE 30.04.23 with response headers:

X-Firefox-Spdy  h2
accept-ranges   bytes
access-control-allow-origin *
content-length  426
content-type    application/manifest+json
date    Sun, 30 Apr 2023 11:46:08 GMT
last-modified   Tue, 01 Feb 2022 09:35:40 GMT
server  LiteSpeed
strict-transport-security   max-age=31536000
vary    User-Agent
x-content-type-options  nosniff
x-frame-options SAMEORIGIN
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding gzip, deflate, br
Accept-Language en-GB,en;q=0.5
Connection  keep-alive
Host    www.[mysite]
Sec-Fetch-Dest  document
Sec-Fetch-Mode  navigate
Sec-Fetch-Site  none
Sec-Fetch-User  ?1
TE  trailers
Upgrade-Insecure-Requests   1
User-Agent  Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0

1 Answer 1

ExpiresByType <mime-type> "access plus 1 year"

The <mime-type> you need to use here is dependent on the mime-type that your server is using in the response. ie. The value of the Content-Type HTTP response header.

However, unless you've explicitly configured a mime-type for .webmanifest files then the server is likely defaulting to application/octet-stream - on which you should probably not set a caching directive.

You could set the appropriate mime-type using the AddType directive. For example:

AddType application/json .webmanifest

You can then use application/json in the ExpiresByType directive, as you did initially. (Making sure that the server is actually honoring that directive and setting the Content-Type header as expected.)

Alternatively, set the Cache-Control (max-age) header directly using mod_headers, based on the file extension (.webmanifest) instead - which is what mod_expires (ExpiresByType) will do. (mod_headers will override mod_expires). For example:

<Files "*.webmanifest">
    Header set Cache-Control "max-age:31536000, must-revalidate"

Where 31536000 is the number of seconds in 1 year (365 days).

Strictly speaking, mod_expires also sets the Expires header as well, but that's only necessary for very old user-agents. (And Expires takes a HTTP-date timestamp, which is tricky to set to a calculated date some period in the future. Cache-Control/max-age conveniently gets round that problem.)

so maybe I don't need this file at all?

Probably not. And I wonder whether it should be cached anyway (or whether that really matters)?

UPDATE: Following your update with the HTTP response headers...

content-type    application/manifest+json
date    Sun, 30 Apr 2023 11:46:08 GMT
last-modified   Tue, 01 Feb 2022 09:35:40 GMT
server  LiteSpeed

As mentioned at the top of my answer. The mime-type that should be used in the ExpiresByType directive corresponds to the mime-type sent back in the Content-Type header. In other words:

ExpiresByType application/manifest+json "access plus 1 year"

(Side note: In your question you are using curly quotes in the above directive - you should be using the plain straight quotes in the config file. Using curly quotes here would be an error.)

However, since there is a Last-Modified header set in the past, this resource will still be cached by the user-agent/browser using heuristic caching - it's just that the duration of this cache will possibly vary by user-agent (it won't be "1 year"), but should increase with time (assuming this file is not updated).

So, the "warning" returned from webpagetest.org is not the complete picture. Yes, there are "No max-age or expires" headers, but that does not necessarily mean the resource won't be cached.

<FilesMatch "*.webmanifest">
    <IfModule mod_headers.c>
        Header set Cache-Control "max-age:31536000, must-revalidate"     

Since you are on a LiteSpeed server (not Apache), this explains why you were not seeing a fatal error with the invalid code (invalid regex) as posted in the comment below (copied above). LiteSpeed tends to simply ignore directives that trigger an "error" (a nightmare to debug, but your site doesn't break).

The FilesMatch directive takes a regex (*.webmanifest is an invalid regex). Whereas the Files directive takes a wildcard-pattern (not a regex). To target just that one file then you could simply uses the entire filename. For example:

<Files "site.webmanifest">

Note that the Files (and FilesMatch) directive(s) match against the filename only, not the file-path.

You should not use the <Ifmodule mod_headers.c> here. Apart from being entirely superfluous on LiteSpeed (it ignores errors anyway), it would only serve to mask errors on Apache. The Header directive is not intended to be "optional" here (the only reason to use the <IfModule> wrapper in this instance).

  • Thank you for these options. I couldn't get the AddType option to work - perhaps because I'm on a shared server (and I did leave it 24 hours before checking again) - but the Cache-Control (max-age) worked fine straight away. I did, however, have to change the code slightly to this: <FilesMatch "*.webmanifest"> <IfModule mod_headers.c> Header set Cache-Control "max-age:31536000, must-revalidate" </IfModule> </FilesMatch>
    – Gillian
    Commented Apr 29, 2023 at 11:13
  • Sorry. I just tested again and I'm still getting the 'fail' message. I'm going to check with my hosts to see if there's a server setting they can change.
    – Gillian
    Commented Apr 29, 2023 at 11:33
  • @Gillian "however, have to change the code slightly" - The code you posted in the comment is not valid (the regex is invalid - I would have expected this to have resulted in an error? Are you on LiteSpeed by chance?) You should not include the <IfModule mod_headers.c> wrapper. The code I posted with <Files "*.webmanifest"> (not FilesMatch) should be OK. You could also state the entire file if this is a one-off, eg. <Files "site.webmanifest">. What other directives do you have the .htaccess file - maybe you have a conflict? (Update your Q with your complete .htaccess file.)
    – MrWhite
    Commented Apr 29, 2023 at 12:22
  • @Gillian Instead of using an external tool, just make a request for this file yourself in the browser and record the HTTP response headers. (Add these to your question.)
    – MrWhite
    Commented Apr 29, 2023 at 12:23
  • 1
    Thanks. Sorry about editing the wrong post. I woke up in the night thinking that's what I'd done! I'm not sure where the curly brackets came in. They're not in the .htaccess file so I believe it's a typing issue when I was preparing my post. So, I added this to the file: <IfModule> AddType application/manifest+json webmanifest </IfModule> and ExpiresByType application/manifest+json "access plus 1 year" and it now works.
    – Gillian
    Commented May 1, 2023 at 11:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.