IIS 7.x cache optimizations

I find myself searching for this information over and over again for each web site I develop, so I guess I must blog this topic to remember it from now on.

IIS 7 has a very powerful caching framework, but some of the defaults are in my opinion not very well thought for modern web applications. For example: by default Javascript files are not compressed with GZIP, and cache location for static content is not public by default. So, if you use T4MVC, SquishtIt, or any other means to link to your static files with a timestamp then you might want to use settings along these lines:

<system.webserver>
  <!-- Omitted Some settings for brevity-->
  <!-- ... -->
  <httpProtocol>
    <customHeaders>
      <!-- Remove notion about ASP.NET -->
      <remove
        name="X-Powered-By" />
    </customHeaders>
  </httpProtocol>
  <staticContent>
    <!--Enable gzipping JS by changing the mime type.
    The IIS default mime type is not gzipped-->
    <remove
        fileExtension=".js" />
    <mimeMap
        fileExtension=".js"
        mimeType="text/javascript" />

    <!--Add a long expires cache header-->
    <clientCache
        cacheControlMode="UseExpires"
        httpExpires="Tue, 19 Jan 2038 03:14:07 GMT" />
  </staticContent>
  <urlCompression
        doDynamicCompression="true"
        doStaticCompression="true"
        dynamicCompressionBeforeCache="true"/>
  <caching>
    <profiles>
      <add
        extension=".gif"
        policy="CacheUntilChange"
        kernelCachePolicy="CacheUntilChange"
        location="Any" />
      <add
        extension=".ico"
        policy="CacheUntilChange"
        kernelCachePolicy="CacheUntilChange"
        location="Any" />
      <add
        extension=".png"
        policy="CacheUntilChange"
        kernelCachePolicy="CacheUntilChange"
        location="Any" />
      <add
        extension=".js"
        policy="CacheUntilChange"
        kernelCachePolicy="CacheUntilChange"
        location="Any" />
      <add
        extension=".css"
        policy="CacheUntilChange"
        kernelCachePolicy="CacheUntilChange"
        location="Any" />
    </profiles>
  </caching>
</system.webserver>

After changes check results with YSlow! or by manually examining response headers. Remember that IIS optimizes compression by not starting it if it is not required: you have to call the site from two different IP addresses from two different machines before IIS compresses responses.