The .htaccess file at the WordPress root controls rewrites, security, caching, and redirects. Every production site needs a hardened .htaccess.
Standard WordPress Rewrite Rules
# BEGIN WordPress
<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
Security Hardening
# Block wp-config.php access
<files wp-config.php>
order allow,deny
deny from all
</files>
# Block xmlrpc.php (if not using Jetpack or remote publishing)
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
# Disable directory browsing
Options -Indexes
# Block sensitive file types
<FilesMatch "\.(htaccess|htpasswd|ini|log|sh|sql|bak)$">
Order Allow,Deny
Deny from all
</FilesMatch>
# Block script injection via query string
Options +FollowSymLinks
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
Browser Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
GZIP Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css
AddOutputFilterByType DEFLATE application/xml application/xhtml+xml application/rss+xml
AddOutputFilterByType DEFLATE application/javascript application/x-javascript
</IfModule>
Force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
PHP Limits (Shared Hosting)
php_value memory_limit 256M
php_value max_execution_time 300
php_value upload_max_filesize 64M
php_value post_max_size 64M