
When you have a static site, sometimes you want to get rid of the HTML extensions and those pesky trailing slashes. Here's how I've done it.
Static websites are back in gaining popularity, even in these days where everything can be driven by a database. With tools like Middleman and Jekyll, web developers have the ability to build fairly complex sites and render them as individual, static files.
I've jumped aboard that train. And while the question as to why I did it deserves its own article, I can say the main motivation for me is speed and cost.
I've been transferring a few of my sites to static files using Middleman. To maintain consistency, I wanted to remove all .html extensions and trailing slashes. And while that's a functional benefit, I also like it better cosmetically.
There are a few different ways to go about removing the .html extension. I've found the following to work just fine:
server {
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
}Then we have to make sure Nginx knows what files to look for, and for that we use the try_files directive. We'll look for a file with the current $uri and an .html extension, and if no file exists, we check for a directory with that name and serve the index. Otherwise, we render a 404 error.
server {
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
index index.html;
try_files $uri.html $uri/ $uri =404;
}After that first step, we have a URL without a .html extension. However, if the file of interest was an index.html file, it could still be accessed via the name of the parent directory with a trailing slash.
For me, for example, I was getting a URL at https://example.com/page/2/, but I didn't want the trailing slash.
We have to remove the trailing slash after we have removed the .html extension.
The gotcha here is that we have to alter the try_files directive to look for an index.html file first.
server {
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
rewrite ^/(.*)/$ /$1 permanent;
index index.html;
try_files $uri/index.html $uri.html $uri/ $uri =404;
}To pull it all together, I'll share a slightly-altered version of my config for this site.
server {
listen 80;
server_name example.com *.example.com;
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
rewrite ^/(.*)/$ /$1 permanent;
root /path/to/project/root;
index index.html;
try_files $uri/index.html $uri.html $uri/ $uri =404;
error_page 404 /404.html;
error_page 500 502 503 504 /500.html;
}A quick thanks to Jason Garber for his note on falling back to $uri within the try_files directive.