As suggested by an answer on SO, I'm trying using a version number on my JS and CSS files so that the browser will only make a request when the JS or CSS version number is changed in my PHP file. To facilitate this, I have a rewrite in my httpd.conf which transforms a requested file like myscript--20140904.js to myscript.js. Since I'm doing things this way, I want the browser to cache the file for a long time, since it will see a request for a "different" file when that version number is updated.

According to an answer on Webmasters.SE, I can use FilesMatch along with Header set Cache-Control to only cache the CSS/JS files with the version number on them.

And according to an answer on SO, only Cache-Control is necessary, since it takes precedence over Expires anyway.

But this is not working. The Cache-Control header field is missing from the response.

Here's my Apache configuration:

RewriteEngine on
RewriteRule ^(.*)\-\-.+\.(css|js)$ $1.$2

<IfModule mod_headers.c>
    <FilesMatch "^(.*)\-\-.+\.(js|css)$">
        Header set Cache-Control "max-age=15552000"
        Header unset ETag
        Header unset Last-Modified

# <IfModule mod_expires.c>
#     <FilesMatch "\.(js|css)$">
#         ExpiresActive On
#         ExpiresByType text/javascript "access plus 6 months"
#         ExpiresByType text/css "access plus 6 months"
#     </FilesMatch>
# </IfModule>

Here's a request for one of the JS files:


GET [url]/common.js HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/[refererUrl]
Cookie: PHPSESSID=[cookie]
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Date: Thu, 04 Sep 2014 19:45:32 GMT
Server: Apache
Last-Modified: Wed, 03 Sep 2014 22:55:57 GMT
Etag: [etag]
Accept-Ranges: bytes
Content-Length: 5167
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/javascript
  • Have you tried it without using <IfModule mod_headers.c>, FilesMatch should be enough. Sep 5 '14 at 8:59
<FilesMatch "^(.*)\-\-.+\.(js|css)$">

FilesMatch takes a filename and matches against the file system, not the URL. The underlying file is still called "myscript.js", so this pattern should be something like: \.(js|css)$

(Aside... your example request appears to be for common.js - which wouldn't have matched your pattern anyway - shouldn't this be for common--20140904.js?)

  • Whoops, using common.js was a typo. I was picking them from a list of headers. The info otherwise was the same though. Sep 5 '14 at 20:36
  • Are you saying I should be using something other than FilesMatch? I was matching the filename, not the url. Sep 5 '14 at 20:37
  • No, I think FilesMatch should be OK. However, you weren't matching the filename, you were trying to match the URL. The regex ^(.*)\-\-.+\.(js|css)$ would only match a filename of the form common--20140904.js, but that is the URL. The filename is simply common.js, which the regex would not match.
    – MrWhite
    Sep 5 '14 at 21:16
  • Oh, I see now... Yes, you're totally right. Thanks! Sep 5 '14 at 22:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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