DEV Community

Andrew Welch
Andrew Welch

Posted on • Originally published at nystudio107.com on

Stop using .htaccess files! No, really.

Stop using .htaccess files! No, really.

Every CMS under the sun has you con­fig­ure a .htac­cess file if you’re using Apache. Don’t do it!

Andrew Welch / nystudio107

997321 Code

Stop using .htaccess files! It seems like heresy. The .htaccess file has been a stan­dard part of the web­dev world for so long, it’s like an old friend. And yet, it’s time to say goodbye.

.htaccess files were born out of an era when shared host­ing was com­mon­place: sysad­mins need­ed a way to allow mul­ti­ple clients to access their serv­er under dif­fer­ent accounts, with dif­fer­ent con­fig­u­ra­tions for their web­sites. The .htaccess file allowed them to mod­i­fy how Apache works with­out hav­ing access to the entire server.

The Vir­tu­al Pri­vate Serv­er, or VPS, has made this a thing of the past. Excel­lent host­ing com­pa­nies like Lin­ode, Dig­i­tal Ocean, Vul­tr, etc. give you an entire vir­tu­al­ized serv­er that is com­plete­ly insu­lat­ed and self-con­tained. And yet, like an appen­dix, .htaccess persists.

Indeed, mod­ern web servers such as Nginx don’t even have the con­cept of a .htaccess file, because times have changed.

Why does it mat­ter, you say? In a word: per­for­mance. Don’t take my word for it, here’s what the Apache Foun­da­tion (the cre­ators of Apache) have to say:

                            You should avoid using .htac­cess files com­plete­ly if you have access to httpd main serv­er con­fig file. Using .htac­cess files slows down your Apache http serv­er. Any direc­tive that you can include in a .htac­cess file is bet­ter set in a Direc­to­ry block, as it will have the same effect with bet­ter performance.
Enter fullscreen mode Exit fullscreen mode

The high­ly regard­ed HTML5 Boil­er­plate warns against it as well:

                            (!) Using ‘.htac­cess‘ files slows down Apache, there­fore, if you have access to the main serv­er con­fig­u­ra­tion file (which is usu­al­ly called <span></span>​<span>‘</span>httpd.conf‘), you should add this log­ic there.
Enter fullscreen mode Exit fullscreen mode

They even have an entire sec­tion on apache.org devot­ed to When (not) to use .htac­cess files. In a nut­shell, if you are using .htaccess files, every sin­gle request the web­serv­er han­dles — even for the lowli­est .png or .css file — caus­es Apache to:

  • Look for a .htaccess file in the direc­to­ry of the cur­rent request
  • Then look for a .htaccess file in every direc­to­ry from there up to the serv­er root
  • Coa­lesce all of these .htaccess files together
  • Recon­fig­ure the web­serv­er using the new settings
  • Final­ly, deliv­er the file

Every. Sin­gle. Request. And every web­page can gen­er­ate dozens of requests. This is over­head you don’t need, and what’s more, it’s com­plete­ly unnec­es­sary unless you are in an old-style shared host­ing envi­ron­ment (and if you are, stop read­ing this arti­cle and switch to a mod­ern VPS immediately).

The prob­lem gets worse the more things are added to the .htaccess file. Often it’s a dump­ing ground for things like rewrite rules and such, and the more com­plex your .htaccess file is, the more over­head is added when Apache has to parse it for every request.

Tan­gent: A bet­ter solu­tion for 301 redi­rects is to have the CMS sys­tem process the redi­rects only after a 404 excep­tion has occurred, ala the Retour plu­g­in for Craft CMS. The ratio­nale is that it’s bet­ter to have the web­serv­er be per­for­mant for the major­i­ty of nor­mal requests, rather than the excep­tion­al redi­rect requests. There are excep­tions, of course: the httphttps redi­rect should always stay serv­er-side, because of how fre­quent­ly it occurs.

Here’s the default .htaccess file that ships with Craft CMS:


<IfModule mod_rewrite.c>
    RewriteEngine On

    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
    RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>

Enter fullscreen mode Exit fullscreen mode

Looks sim­ple enough. It’s just doing some fan­cy stuff to make sure you can have pret­ty look­ing URLs with­out index.php in them, and to make sure that 404 errors are rout­ed through Craft. This is pret­ty typ­i­cal of what many CMS sys­tems have you put into a .htaccess file.

For every domain on your web­serv­er, there is a Vir­tu­al Host file that tells the web­serv­er how to serve the web pages for that domain. All we need to do is trans­fer what we used to put in our .htaccess file into the Vir­tu­al Host file, and we’re done. It’s real­ly that easy.

Every­thing from your http -> https rewrite rules to expires head­ers, gzip com­pres­sion set­tings, and oth­er per­for­mance enhance­ment set­tings will all work too.

                            If it worked in .htac­cess, it will work in your vir­tu­al host .conf file as well. Both are just ways to con­fig­ure your web­serv­er, but doing it once when the web­serv­er starts up vs. every request is more performant.
Enter fullscreen mode Exit fullscreen mode

Git ​’Er Done

Since you’ve actu­al­ly read this far, I’ll assume you’re onboard with free­ing your­self from using .htaccess files. But how do we do it? Sim­ple. We just need to take the direc­tives that were in the .htaccess file, and put them in our Vir­tu­al Host .conf file. These files are usu­al­ly locat­ed in /etc/httpd/conf.d or /etc/httpd/sites-available on most Lin­ux distributions.

There is one oth­er small thing we must do as well. Even if we don’t even have a .htaccess file on our serv­er, Apache will still look for them if the AllowOverride direc­tive tells it to. So we just set AllowOverride none in our Vir­tu­al Host file, and that tells Apache that it does­n’t need to look for .htaccess files anymore.

Here’s what a com­plete Vir­tu­al Host .conf file looks like for Craft CMS. Oth­er CMS sys­tems should look pret­ty similar:


<VirtualHost *:80>
  ServerName BradsForMen.com
  ServerAlias *.BradsForMen.com
  DocumentRoot /var/www/BradsForMen/public
  CustomLog /var/log/httpd/BradsForMen.com-access.log combined
  ErrorLog /var/log/httpd/BradsForMen.com-error.log

## Canonical domain rewrite ##
  <If "%{HTTP_HOST} != 'BradsForMen.com'">
    Redirect "/" "http://BradsForMen.com/"
  </If>

  <Directory /var/www/BradsForMen>
      Options FollowSymLinks
      AllowOverride None

## Removes index.php from Craft URLs ##
      <IfModule mod_rewrite.c>
        RewriteEngine On
        # Send would-be 404 requests to Craft
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
        RewriteRule ^(.+) /index.php?p=$1 [QSA,L]
      </IfModule>
  </Directory>
</VirtualHost>

Enter fullscreen mode Exit fullscreen mode

Note that we sub­tly changed the regex from RewriteRule (.+) index.php?p=$1 [QSA,L] to RewriteRule ^(.+) /index.php?p=$1 [QSA,L]

That’s it. Save it, restart Apache with sudo apachectl restart, and away you go!

You may ask how much of a dif­fer­ence this makes. In truth, it’s not a huge gain. You can expect about a gain in the sin­gle dig­its, which will become a greater impact as traf­fic increas­es. How­ev­er, giv­en how com­plete­ly unnec­es­sary it is to use .htaccess files, there’s real­ly no rea­son not to imple­ment the best prac­tice of eschew­ing its use.

Even seem­ing­ly small per­for­mance gains add up when imple­ment­ed together.

Further Reading

If you want to be notified about new articles, follow nystudio107 on Twitter.

Copyright ©2020 nystudio107. Designed by nystudio107

Top comments (1)

Collapse
 
olsard profile image
olsard

Nice, thanks for sharing!