Basics about .htaccess in WordPress
The .htaccess file (hypertext access) lets you manage the configuration of your web server. Even a small change in this file can break and take down an entire website. Therefore it is always recommended to take a backup before touching the .htaccess file. The best way is to just use an FTP client like Filezilla and download the file to your local computer before even opening it.
We can use the .htaccess file as follows…
- Redirect rules
- Blocking and allowing access to the site from defined IP addresses
- Password protect individual folders on your web server
- Performance improvement by enabling compression and caching
- Overwriting PHP.ini settings (e.g. maximum upload size)
- … many other
Default .htaccess file
Every WordPress instance comes with this default .htaccess file located on your root directory (e.g. /home/markus/public_html) on your webserver.
# BEGIN WordPress
# The directives (lines) between `BEGIN WordPress` and `END WordPress` are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Force HTTPs via .htaccess
It needs more than just a rule in your .htaccess file to make your site secure. First, you need an SSL certificate, you need the rewrite rule in .htaccess, you need to change the WordPress Address (URL) and Site Address (URL) in your WordPress Backend setting (or wp-config.php, or functions.php, or database), and you need to guarantee that your site does not contain any HTTP links, e.g. to images or other sources you use.
There is a lot to take care of when you want to get your site secured and unfortunately it is absolutely necessary. What’s confusing for a beginner (and even advanced) WordPress user is the possible combination of applying those things. For instance is it possible to force a redirect from HTTP to HTTPs via .htaccess, via hosting provider, and via a CDN like Cloudflare.
WordPress Address (URL) |
---|
Site Address (URL) |
---|
For now, we only have a look at the rules that must be added to the .htaccess file.
Add before # BEGIN WORDPRESS
section
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Full .htaccess file including force HTTPs and default entries
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# BEGIN WordPress
# The directives (lines) between `BEGIN WordPress` and `END WordPress` are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Enable Deflate Compression (mod_deflate)
! Unclear at the current moment how such settings in .htaccess interfere with WordPress plugins or CDN promising the same results
# BEGIN DEFLATE COMPRESSION
<IfModule mod_deflate.c>
# Compress HTML, CSS, JavaScript, Text, XML and fonts
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>
# END DEFLATE COMPRESSION
Enable GZIP Compression (mod_gzip)
! Unclear at the current moment how such settings in .htaccess interfere with WordPress plugins or CDN promising the same results
# BEGIN 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>
# END GZIP COMPRESSION
Enable expired headers (mod_expires)
Expires headers tell browsers files won’t change for a certain time, meaning those browsers don’t have to reload them each time.
! Unclear at the current moment how such settings in .htaccess interfere with WordPress plugins or CDN promising the same results
#BEGIN EXPIRES HEADERS
<IfModule mod_expires.c>
# Enable expirations
ExpiresActive On
# Default expiration: 1 hour after request
ExpiresDefault "now plus 1 hour"
# CSS and JS expiration: 1 week after request
ExpiresByType text/css "now plus 1 week"
ExpiresByType application/javascript "now plus 1 week"
ExpiresByType application/x-javascript "now plus 1 week"
# Image files expiration: 1 month after request
ExpiresByType image/bmp "now plus 1 month"
ExpiresByType image/gif "now plus 1 month"
ExpiresByType image/jpeg "now plus 1 month"
ExpiresByType image/jp2 "now plus 1 month"
ExpiresByType image/pipeg "now plus 1 month"
ExpiresByType image/png "now plus 1 month"
ExpiresByType image/svg+xml "now plus 1 month"
ExpiresByType image/tiff "now plus 1 month"
ExpiresByType image/vnd.microsoft.icon "now plus 1 month"
ExpiresByType image/x-icon "now plus 1 month"
ExpiresByType image/ico "now plus 1 month"
ExpiresByType image/icon "now plus 1 month"
ExpiresByType text/ico "now plus 1 month"
ExpiresByType application/ico "now plus 1 month"
# Webfonts
ExpiresByType font/truetype "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
</IfModule>
#END EXPIRES HEADERS