Traditionally, web sites use either www or non-www version to display their content to the visitors. Sub-domains are also becoming popular in recent times. When www is chosen as the preferred domain when installing WordPress (or after installing WordPress), whenever a visitor types non-www version of the site, WordPress redirects the visitor to the correct URL, the www version the site, through an internal 301 redirect. Google recommends this 301 redirect and Google WebMaster Tools has an option to set the preferred domain too.
In performance optimization, every tiny improvement helps to speed up and scale up the site. When 301 redirect is done by WordPress, it requires PHP to be processed. When 301 redirect is done at the server level, without using PHP, the process is more efficient, so requires less time to execute.
Let’s see how newbie webmasters traditionally set up 301 redirects in Apache and in Nginx…
Apache 301 redirect (non-www to www – traditional way)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domainname\.com$ [NC]
RewriteRule ^(.*)$ http://www.domainname.com/$1 [R=301,L]
</IfModule>
Apache 301 redirect (www to non-www – traditional way)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.domainname\.com$ [NC]
RewriteRule ^(.*)$ http://domainname.com/$1 [R=301,L]
</IfModule>
Nginx 301 redirect (non-www to www – traditional way)
server {
server_name domainname.com;
rewrite ^/(.*)$ http://www.domain.com/$1 permanent;
}
Nginx 301 redirect (www to non-www – traditional way)
server {
server_name www.domainname.com;
rewrite ^/(.*)$ http://domain.com/$1 permanent;
}
As already mentioned, above methods are done at the server level that is more efficient than doing at the application level (read application = WordPress) and every bit of improvements helps. So, let’s break the tradition and see how we could achieve the same in a more efficient way, using Apache and Nginx.
In Apache, we need to split the virtualhost entries like below…
Apache 301 redirect (non-www to www – new, efficient, & the best way)
# Assuming that Apache listens on 127.0.0.1
<VirtualHost 127.0.0.1>
ServerName domainname.com
<IfModule mod_alias.c>
Redirect permanent / http://www.domainname.com/
</IfModule>
</VirtualHost>
<VirtualHost 127.0.0.1>
ServerName www.domainname.com
# other directives to process www.domainname.com
</VirtualHost>
Apache 301 redirect (www to non-www – new, efficient, & the best way)
# Assuming that Apache listens on 127.0.0.1
<VirtualHost 127.0.0.1>
ServerName www.domainname.com
<IfModule mod_alias.c>
Redirect permanent / http://domainname.com/
</IfModule>
</VirtualHost>
<VirtualHost 127.0.0.1>
ServerName domainname.com
# other directives to process domainname.com
</VirtualHost>
The above examples assume that mod_alias Apache module is present in the server. When in doubt, ask your host or server admin. For the following examples that use Nginx, no extra modules needed to make them work. The return directive is part of the standard Rewrite module in Nginx.
Nginx 301 redirect (non-www to www – new, efficient, & the best way)
server {
server_name domainname.com;
return 301 $scheme://www.domainname.com$request_uri;
}
Nginx 301 redirect (www to non-www – new, efficient, & the best way)
server {
server_name www.domainname.com;
return 301 $scheme://domainname.com$request_uri;
}
In the above examples, by using Redirect directive of Apache and return directive of Nginx, we can effectively avoid doing any capturing or matching at all and thus we can completely avoid evaluation of a regular expression.
If you are using Varnish, then I already published a blog post on how to do 301 redirects using Varnish.
Update: On March 11, 2017
Nekraj Bharitya asked a good question in the comments…
Question: How can we check wheter my site is using 301 or 302 redirect?
Answer: We may use an online tool such as Redbot to check it.
Hi,
I included your rewrite rules, when I restart nginx I get the following warning:
nginx: [warn] server name “$scheme://www.XXXXXXX.tld$request_uri” has suspicious symbols
Hi Gary,
There was a missing semicolon in my configuration. Fixed it now. Please try again.
Thanks for pointing it out.
Pothi
Thanks, that was the problem indeed – error message disappeared now!
Using the “Redirect permanent” method causes a redirect loop because there is no condition to fulfill.
At least that is what I get on my test Apache servers using Firefox and Chrome.
Good catch! Now, I’ve clarified my code, in the post. Thanks for pointing it out!
No problem, glad I could help.
Unfortunately, this new method requires that you have access to the server config file… something not usually permitted on shared hosts.
Hello,
Excellent article!
However, it’s not working for me. I’m using apache 2.4 (in Centos 7), and am trying to use the www to non-www redirect. It’s working for http, but not for https.
I’ve tested both options (traditional and new), with the same results.
Any issue with apache 2.4 regarding this?
Thanks!
How can I check wheter my site is using 301 or 302 redirect?Plus is it neccesary?
Hi Nekraj,
Good question. Sorry, I didn’t answer it in the article.
You may use an online tool, such as https://redbot.org to find what’s used on your site. I went on and checked your site. Your site indeed uses 301. Ref: https://redbot.org/?uri=http%3A%2F%2Fseofreetips.net.
The necessity depends on lots of factors. For SEO, yes!
Thanks You Pothi Kalimuthu to solve one of my query.
Please after doing 301 redirection, should i make all the search engines aware of the url redirection all they will get to know with time??
Search engines would be aware of the changes when they visit your site again!
I used:
# Assuming that Apache listens on 127.0.0.1
ServerName domainname.com
Redirect permanent / http://www.domainname.com/
ServerName http://www.domainname.com
# other directives to process http://www.domainname.com
And ended up with the site not working due to 19 redirects. TOO MANY REDIRECTS ERROR
Sorry about that. I haven’t used Apache for a while. So, I haven’t tested it with the recent versions of Apache. Probably, something is indeed wrong with my example code.