Generate .htaccess in Middleman
Writing .htaccess file manually can be exhausting because a lot of Apache directives must be duplicated. If you use Middleman for generating static websites, you can use it for .htaccess too. My rule of thumb is that any directive should be only once in .htaccess. Define source data in yml file and loop the data in htaccess template without layout.
But there is one catch. Middleman v3 automatically appends html file extension. So add dummy extension to .htaccess file and rename the file after build. I would not use html or other well known extension because minifiers or other plugins could cause unexpected errors.
Example
It's completely up to you which directives will you use. If you have existing .htaccess, then simply extract duplicated directives. Below you can see configuration for one of my website:
- Redirects example.com to www.example.com
- Redirects old urls to new urls with status code
301 Moved Permanently
- Deflate + cache images, CSS, JavaScript files
- Add custom error documents
config.rb
# disable layout
page ".htaccess.apache", :layout => false
# rename file after build
after_build do
File.rename 'build/.htaccess.apache', 'build/.htaccess'
end
data/htaccess.yml
web:
domain: example.com
url: http://www.example.com
redirect:
/old-url.html: /new-url.html
/another/url.html: /new/
cache:
deflate: \\.(js|css|html|ico|png)$
expire:
image/png: access plus 1 month
image/ico: access plus 1 month
image/x-icon: access plus 1 month
text/html: access plus 1 minute
text/css: access plus 7 days
application/javascript: access plus 7 days
text/javascript: access plus 7 days
errors:
401: "Unauthorized access"
404: /404.html
source/.htaccess.apache.erb
# MOVE PERMANENTLY
<% data.htaccess.redirect.each do |old, new| %>
Redirect 301 <%= old %> <%= data.htaccess.web.url %><%= new %>
<% end %>
# REWRITE - redirect to www. page
RewriteEngine on
RewriteCond %{HTTP_HOST} ^<%= data.htaccess.web.domain %>$
RewriteRule (.*) <%= data.htaccess.web.url %>/$1 [R=301,L]
# ERROR DOCUMENTS
<% data.htaccess.errors.each do |code, document| %>
ErrorDocument <%= code %> <%= document %>
<% end %>
# GZIP, CACHE
AddType image/x-icon .ico
ExpiresActive on
<% data.htaccess.cache.expire.each do |type, expire| %>
ExpiresByType <%= type %> "<%= expire %>"
<% end %>
<FilesMatch "<%= data.htaccess.cache.deflate %>">
SetOutputFilter DEFLATE
</FilesMatch>