Skip to content

Instantly share code, notes, and snippets.

@Zodiac1978
Last active March 15, 2024 08:29
Show Gist options
  • Save Zodiac1978/3145830 to your computer and use it in GitHub Desktop.
Save Zodiac1978/3145830 to your computer and use it in GitHub Desktop.
Make your Website faster - a safe htaccess way
#
# Sources:
# http://stackoverflow.com/questions/7704624/how-can-i-use-gzip-compression-for-css-and-js-files-on-my-websites
# http://codex.wordpress.org/Output_Compression
# http://www.perun.net/2009/06/06/wordpress-websites-beschleuinigen-4-ein-zwischenergebnis/#comment-61086
# http://www.smashingmagazine.com/smashing-book-1/performance-optimization-for-websites-part-2-of-2/
# http://gtmetrix.com/configure-entity-tags-etags.html
# http://de.slideshare.net/walterebert/die-htaccessrichtignutzenwchh2014
# http://de.slideshare.net/walterebert/mehr-performance-fr-wordpress
# https://andreashecht-blog.de/4183/
#
<IfModule mod_deflate.c>
# Insert filters / compress text, html, javascript, css, xml:
# mod_deflate can be used for Apache v2 and later and is the recommended GZip mechanism to use
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/vtt
AddOutputFilterByType DEFLATE text/x-component
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/js
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/atom+xml
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/font-sfnt
AddOutputFilterByType DEFLATE application/x-web-app-manifest+json
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/sfnt
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
# Exception: Images
SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png)$ no-gzip dont-vary
# Drop problematic browsers
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
# Make sure proxies don't deliver the wrong content
<IfModule mod_headers.c>
Header append Vary User-Agent env=!dont-vary
</IfModule>
</IfModule>
# mod_gzip is an external extension and last updated 2015, so
# if available please use mod_deflate instead
# If you are stuck on Apache v1.3 you can use mod_zip to enable Gzip
# as mod_deflate is available for Apache v2 or later only.
<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>
## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rdf+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/ld+json "access plus 0 seconds"
ExpiresByType application/schema+json "access plus 0 seconds"
ExpiresByType application/vnd.geo+json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 month"
ExpiresByType text/html "access plus 1 minute"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 months"
ExpiresByType application/x-javascript "access plus 1 months"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
ExpiresByType text/plain "access plus 1 month"
ExpiresByType text/x-component "access plus 1 month"
ExpiresByType application/manifest+json "access plus 1 week"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType font/eot "access plus 1 month"
ExpiresByType font/opentype "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 application/x-font-woff "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"
</IfModule>
## EXPIRES CACHING ##
#Alternative caching using Apache's "mod_headers", if it's installed.
#Caching of common files - ENABLED
<IfModule mod_headers.c>
# 1 Month
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>
# 2 DAYS
<FilesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=172800, public, must-revalidate"
</FilesMatch>
# 2 HOURS
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</FilesMatch>
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(js|css|xml|gz|html|ttf)$">
Header append Vary: Accept-Encoding
</FilesMatch>
</IfModule>
# Set Keep Alive Header
# This *just* sets the header - maybe your hoster is not allowing this feature
# Please check if it is working with tools like http://www.webpagetest.org
<IfModule mod_headers.c>
Header set Connection keep-alive
</IfModule>
# If your server don't support ETags deactivate with "None" (and remove header)
<IfModule mod_expires.c>
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
</IfModule>
@mortensassi
Copy link

Thanks for sharing!
I'm using Wordpress with VueJS and i can't get the wp-json responses gzipped
Copied this htaccess to both my / where the Frontend is located and for /be where my wordpress is located

This is what pingdom is telling me:

The following cacheable resources have a short freshness lifetime. Specify an expiration at least one week in the future for the following resources:
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/footer-menu
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/header-menu
https://site.com/be/wp-json/wp/v2/projects
The following resources are missing a cache validator. Resources that do not specify a cache validator cannot be refreshed efficiently. Specify a Last-Modified or ETag header to enable cache validation for the following resources:
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/footer-menu
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/header-menu
https://site.com/be/wp-json/wp/v2/projects
The following publicly cacheable, compressible resources should have a "Vary: Accept-Encoding" header:
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/footer-menu
https://site.com/be/wp-json/wp-api-menus/v2/menu-locations/header-menu
https://site.com/be/wp-json/wp/v2/projects

@codeclinic
Copy link

mod_deflate is now the recommended option over mod_gzip.

@Zodiac1978
Copy link
Author

Hi @mortensassi this should be working if your host is using mod_deflate because of these lines:
https://gist.github.com/Zodiac1978/3145830#file-htaccess-L30-L31

@Zodiac1978
Copy link
Author

Hi @codeclinic - what do you recommend to change (as this gist is using mod_gzip and mod_deflate)?

@yashodhank
Copy link

yashodhank commented Jun 23, 2019

mod_gzip is legacy module Apache 1.3 and bellow.
mod_deflate is compatible with Apache 2.0 and above.

@Zodiac1978
Copy link
Author

@yashodhank Thanks for the explanation. I will add some more explanations as comments!

@wlarch
Copy link

wlarch commented Jul 16, 2020

Thanks for the Gist ! Very helpful.
In our case, we used the "modification" flag for the mod_expires.

Example :

ExpiresByType text/javascript "modification plus 1 year"

@Zodiac1978
Copy link
Author

Zodiac1978 commented Mar 26, 2021

Update: Added some more font mime types: font/sfnt, application/font-sfnt, font/otf and font/ttf

@Barnabas2
Copy link

If using CDN, will editing .htaccess have any effect? Since the request is served by the CDN and not the server?

@Zodiac1978
Copy link
Author

@Barnabas2 No, if the item is loaded from an external CDN the settings from your server (htaccess) have, of course, no effect.

@cutcool
Copy link

cutcool commented Jan 5, 2022

Hello, according to google page speed I don't have the compression of the following files enabled
…css/bootstrap.min.css , …remixicon/remixicon.css, …jquery/jquery.min.js and more but checking the compression in https://www.websiteplanet.com/es/webtools/gzip-compression/ compression is active ... why could google pagespeed not recognize compression?

@Zodiac1978
Copy link
Author

Zodiac1978 commented Jan 6, 2022

@cutcool I recommend to use https://www.webpagetest.org/ - this will give you more insights. If you use this .htaccess settings from above this shouldn't happen if those files are hosted on your server, because CSS and JS files should be compressed.

Are those files really hosted on your server and not from a CDN? Is your server using the mod_deflate module? You can check via phpinfo() (under "Loaded Modules"). (Or mod_gzip if you are on Apache <=1.3)

@monty88
Copy link

monty88 commented Sep 19, 2022

Hello, thank you for sharing that

But, is that work with WordPress ?

@Zodiac1978
Copy link
Author

@monty88 Yes, it is working with WordPress.

@twheel
Copy link

twheel commented Sep 3, 2023

Is there an advantage to caching using both mod_expires ( ExpiresByType...) and mod_headers (Header set Cache-Control...) or is it better to choose one or the other?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment