How to Reduce the size of a Kindle Book

Recently I published an image heavy Kindle title and found that it had quite a large file size. The culprit of course was the number of images. Kindle books only support either the .JPG or .GIF image format, so using highly optimized .PNGs was out of the question.

As I was using Jutoh to write my book, I didn’t have access to the image files used by Jutoh once they had been imported. It would have taken days to reinsert every image file after optimizing them. The quickest way to optimize all images that I found was to compile the book to a .mobi file, use KindleUnpack to unpack the .mobi file, open the zip file containing the source files, optimize all the .gif images using Trout Image Optimizer and then finally open the content.opf file in KindlePreviewer which automatically compiles a new .mobi file with the optimized images.

How to Seriously Speed Up and Optimize WordPress

A few months ago one of my WordPress sites began to get popular with almost 6,000 unique visitors a day. As the site grew, I also noticed that it was getting very slow to load. This post is about how I managed to speed up and optimize my WordPress site to make it blazing fast.

#1. Move Away from Shared Hosting

If you are paying under $10 for hosting a month you are likely on a shared web hosting server. On a shared server there are multiple users running websites alongside yours. If another website served from the same server as yours is popular it will use up a lot of CPU time, memory and bandwidth starving your site of needed resources. Good hosting companies will run their shared server efficiently, making sure that there are not too many sites per server and that the loads are balanced, but there is still no guarantee of minimum performance.

Once your site begins to get popular I recommend moving to a Virtual Private Server (VPS). This is kind of similar to shared hosting in that there are multiple users running sites on the same server. However, the major difference is that each user gets their own dedicated slice of the server resources to do with what they please. This gives a guarantee of minimum performance.

I had previously hosted my sites on Hostgator shared hosting. Once my site got popular I moved my site to a Linode VPS server. This one change made a huge difference in performance. My average site load times we from around 5 seconds down to only 2 seconds. It’s important to note that Linode is an ‘unmanaged’ host. This means that you will need web hosting and Linux experience to set up your sites. Although Linode provides many tutorials, if you are a novice I strongly recommend using managed hosting. One managed host that has the best reviews out there is KnownHost and I recommend considering them for your VPS services.

If you are an absolute complete novice to web hosting and WordPress then I highly recommend you check out WP Engine for your hosting. They are a managed host that specialize in WordPress sites. If you switch to WP Engine for your hosting you can probably ignore most of the tips shown in this post as their staff and infrastructure will take care of all the optimizations for you!

#2. Use WP Supercache

This is an obvious one. If you don’t already have some sort of caching method plugin like WP Supercache installed you should install one now. WordPress sites are dynamically generated. That means that a page’s code is generated from scratch each time it is loaded. This is slow as the server CPU must first spend time generating the page code. A caching plugin saves the generated page code and serves the pre-generated page directly.

Installing WP Supercache is easy, just find it in the WordPress Add New plugins search. Then once downloaded and activated enable caching under the easy tab in the WP Supercache settings page. Now your pages are cached! But to improve caching speed I recommend going into the advanced tab and changing the caching method to mod_rewrite then scrolling down an clicking on the Update Status button. After this you’ll need to scroll down again in the Advanced tab page and click the Update Mod_Rewrite Rules button.

I also recommend using the “Compress pages so they’re served more quickly to visitors” option and also the “Don’t cache pages for known users”. Not caching for known users will ensure that any changes you make to the site that may be cached will show up straight away for you.

#3. Use a CDN

A Content Delivery Network (CDN) will dramatically improve your page load speeds. A CDN company works by having multiple server locations around the world. Instead of a user requesting a page from your server across the world, a CDN will step in and cache elements of the page at a server that is closer to the user. This can help distribute and reduce the load on your server whilst at the same time making your site load faster all around the world.

I suggest that people use the well trusted MaxCDN service. The lowest tier of MaxCDN services costs $9 and includes 100GB of data transfer which should be plenty for any moderately successful site. With a CDN like MaxCDN you will be able to see vastly improved page load times.

There is also Cloudflare which is another CDN provider. As well as paid services Cloudflare provides a free option with reduced performance. You will need to do careful speed testing with the free option however as some users have reported that the free Cloudflare can actually slow down some websites.

#4. Optimize MySQL Databases

Most webservers won’t be set up to automatically optimize your WordPress databases. Optimizing a WordPress database is kind of like dragmenting your PC hard drive. After it is optimized accessing the database will be much much faster. A plugin called WP Optimize can be installed that will automatically optimize your WordPress database. WP Optimize will also remove old post revisions and drafts that eat up database space and increase access times. Please ensure that you first back up your databases before optimizing as in some very rare instances optimization could break a database. I recommend using the Updrafts Plus backups plugin for this purpose.

If you don’t want to use a plugin and you have PHPMyAdmin installed on your server (usually available in most managed hosts and in cPanel through Databases >> phpMyAdmin) you can simply use the dropdown Optimize menu to optimize your databases.

My WordPress database had not been optimized for a year and after optimization its file size halved and there was a noticeable performance boost.

#5. Ensure your site is Compressed

Just like zip files, websites can be compressed before they are sent. This can in many cases significantly reduce the amount of data that needs to be transferred over the internet therefore speeding up page load times.

To check if your site is compressed you can use the online tool at checkgzipcompression.com. If it isn’t already you can enable gzip compression through cPanel if you have it. In cPanel go to Software/Services >> Optimize Website and make sure that the “Compress all content” radio button is selected. The WP Super Cache plugin also has a setting which can be used to serve compressed files.

#6. Use EWWW Image Optimizer

If you have an image heavy site it will pay to use an image optimizer like EWWW. An image optimizer will compress your images optimally to save space and thus improve page load speeds. I recommend enabling Lossy PNG optimization as this will thoroughly optimize PNG images usually without any noticeable loss by removing unused colors. If you run your site on a private server and have a decent CPU setup I recommend also enabling pngout and setting it’s optimization level to extreme.

To optimize any images uploaded before you install EWWW go to Media >> Bulk Optimize and use the options there to optimize old files. If you are on a shared server be careful that you do not set the optimization settings to the maximums as it could use up a lot of shared CPU if you were to try and bulk optimize all your images. On shared hosting using too much CPU might get your account temporarily restricted. For shared hosting, the default settings work well.

#7. Remove or Reduce Share and Follow Buttons

Having too many share and follow buttons on your blog can have a very noticeable affect on page load times. This is because each share button loads code from external servers. Some ways to get around slow share buttons are to load them asynchronously using the Asynchronous Share Buttons plugin. Normally share buttons will load sequentially, that is one after another. With asynchronous buttons they can all load simultaneously.

For follow buttons in the side bar I recommend simply uploading your own images and directly linking your social media pages to the images. Here is some example HTML code. I simply uploaded the sharing icons to my blog and then copy and pasted the link to them in the src=”” section of the code. Place this code into a sidebar text widget and remember to change the images to your own hosted images and the parts of the code that say YOUR_PAGE to your own page.

<h3 class=title>Follow Us</h3><div><a target=_blank rel=nofollow title="Follow us on Facebook" href="http://www.facebook.com/YOUR_PAGE" style="font-size: 0px; width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px;"><img alt=facebook title="Follow us on Facebook" width=48 height=48 style="display: inline; width:48px;height:48px; margin: 0; padding: 0; border: none; box-shadow: none;" src="http://www.rtl-sdr.com/wp-content/uploads/2014/07/facebook.png"/></a><a target=_blank rel=nofollow title="Follow us on Twitter" href="http://twitter.com/YOUR_PAGE" style="font-size: 0px; width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px;"><img alt=twitter title="Follow us on Twitter" width=48 height=48 style="display: inline; width:48px;height:48px; margin: 0; padding: 0; border: none; box-shadow: none;" src="http://www.rtl-sdr.com/wp-content/uploads/2014/07/twitter.png"/></a><a target=_blank rel=nofollow title="Subscribe to our RSS Feed" href="http://www.projectilefish.com/feed/" style="font-size: 0px; width:48px;height:48px;margin:0;margin-bottom:5px;"><img alt=rss title="Subscribe to our RSS Feed" width=48 height=48 style="display: inline; width:48px;height:48px; margin: 0; padding: 0; border: none; box-shadow: none;" src="http://www.rtl-sdr.com/wp-content/uploads/2014/07/rss.png"/></a>

This code will result in the following

Follow Us

facebooktwitterrss

#8. Use Image Thumbnails

When you insert an image into WordPress it is inserted at the full image size. I recommend reducing the image size down to a smaller size for the post. The user can then simply click on the image to view the full sized version. To set thumbnail sizes that should be created go to Settings >> Media in the WordPress Admin area. Choose the sizes that your small, medium and large thumbnails should be. Then to insert a thumbnail simply change the size option to one of the thumbnails when adding or editing the image.

#9. Use a Minifier

A minifier WordPress plugin can be used to help optimize CSS and Javascript code being used on your site. A minifier works by rewriting the CSS or Javascript code down so that its text size is much smaller. This reduces the amount of data that needs to be sent over the internet. There are various minifiers available as plugins and I recommend trying out Autoptimize.

After using a minification plugin you must check that your site functions properly. In some cases minification can break some sites. But don’t worry as changes can be undone simply by removing or turning off the options in the minification plugin.

#10. Add Far Future Expiration for Web Browser Caches

Far Future Expiration sets how long a users web browser will locally cache content. When a user who has locally cached content reloads your page, that content will be served from the users local machine. Generally, we want things like images, icons and fonts to be cached for a long time, like maybe a month or more. Add this to your .htaccess file to enable far future expiration.

# BEGIN Far Future Expiration
<IfModule mod_expires.c>
ExpiresActive on
<FilesMatch "\.(gif|jpeg|jpg|png|ico|woff)$">
ExpiresDefault "access plus 720 hours"
</FilesMatch>
# CSS
ExpiresByType text/css "access 24 hours"
# Javascript
ExpiresByType application/javascript "access plus 24 hours"
</IfModule>
# END Far Future Expiration

#11. Delete Unused Plugins

Every plugin you add to WordPress increases it’s load time. Some more than others. Make sure you are only using plugins that you absolutely need and uninstall any that you are not using.

#12. Use P3 Plugin Profiler

P3 Plugin Profiler is a WordPress plugin that will analyze each plugin you have installed and determine how much CPU time they take up per page load. By using this profiler you can identify any plugins that are causing noticeable performance issues.

#13. Use YouTube Lyte

If you place YouTube videos on your blog you should use the YouTube Lyte plugin. This plugin ‘lazy loads’ the slightly bloated YouTube media player. Lazy loading means that the YouTube media player will only load when the user clicks on the video to watch it. Before that point a simpler lighter display only version of the YouTube media player is shown.

This plugin is especially useful and can make a huge difference if you have multiple YouTube videos per page.

#14. Delete Comment Spam Folder

Another major issue was that with the new found popularity spam bots had begun hitting the site pretty hard. After a month of neglect, my comment spam folder had over 6,000 spam comments marked by Askismet waiting to be cleared. A large amount of comments in the spam folder will increase the comment database size making it slow to access. To fix this simply delete all spam comments from your spam folder.

#15. Set Askismet to Delete Spam Straight Away

If you are using Askismet then to prevent the spam folder from growing too large again I set the Askismet strictness setting to “Silently discard the worst and most pervasive spam so I never see it.” Askismet is a free service that will detect and filter spam comments into your comments spam folder. Though for me at least I find that Askismet causes a lot of false positives. Instead I use a combination of Cookies for Comments (below) and WP-No-Bot-Question to stop spam.

#16. Use the Cookies for Comments Plugin

Although Askismet catches most spam comments it still lets some through every now and then. The plugin “Cookies for Comments” is a highly effective method at stopping comment spam. Essentially it works using two methods. One is that it checks for the presence of cookie that it sets. Spam comment bots often do not store cookies. Secondly, it treats any comment that was posted within X seconds of a page load as spam as it is unlikely that a human would post a comment so fast.

Be sure to add the recommended code to your .htaccess file as this will stop spam bots from even entering your site and eating up precious resources.

An alternative to Cookies for Comments that might work even better at stopping spam is Spam Destroyer. As well as the cookie technique spam destroyer requires the presence of Javascript, which many bots do not have enabled. Although, with Spam Destroyer you cannot block bots through your .htaccess file.

#17. Block XMLRPC Requests

After the site got popular when looking at my server logs one thing that I noticed was an inordinate amount of XMLRPC requests coming through. These requests were eating up significant CPU time and causing large slowdowns. This was probably caused by some sort of malicious bot trying to spam pingbacks or take down the site.

XMLRPC is used by the trackback and pingback functions of WordPress. Some plugins like Jetpack also require it. As I didn’t really need these functions I decided to simply block all XMLRPC requests. This can be done by editing your sites .htaccess file and adding the following code to the top of it.

ErrorDocument 503 "System Undergoing Maintenance"
RewriteEngine On
RewriteCond %{THE_REQUEST} "/xmlrpc.php" [NC]
RewriteRule .* - [R=503,L]

After blocking these spammy requests the server CPU usage went down and the site started loading faster.

#18. Stop WP-Login Attacks

WP-Login attacks are run by bots who attempt to bruteforce their way into your Wordpress account through the WP-Login admin page by guessing passwords many times a second. These attacks can hammer a site causing excessive CPU usage. I recommend using the Security-protection plugin to stop these attacks. WP-Security is my pick as it tricks the bot into believing that it has gained entry thus stopping the attack early and saving you from excessive server load. As a security tip I also recommend not using the ‘admin’ username for your account as the bots often only check this username.

If you have admin access to your server I also recommend setting up a fail2ban jail to stop these attacks.

#19. Use Fail2Ban to stop Repeat Spammers

By using fail2ban together with a WordPress spam logging plugin we can block repeat spammers at the firewall level. This will stop repeat spammers hammering your site and eating up precious resources. This is really only needed if your website it being targeted by aggressive spam bots which try and post a new spam message every few minutes. I used this tutorial to implement fail2ban spam protection.

#20. Install Mod_Evasive

Mod_evasive is a tool that will help your server to evade denial of service (DOS) attacks. If one of these attacks occurs on your server you hosted sites will take a massive performance hit. Mod_evasive blocks access to any IP that is DOSing your site.

#21. Serve Images Directly

I found a modification to the WordPress .htaccess file which will allow images to be served directly without invoking WordPress at all. Credit goes to this post by Rod Holmes. In your .htaccess file find the following

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

and replace it with the following

RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point, you may delete or comment-out the following RewriteBase directive:
#RewriteBase /
#
# if request is for image, css, or js file
RewriteCond %{REQUEST_FILENAME} \.(png|gif|jpe?g|css|js|ico)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]

#22. Upgrade PHP

Many servers are still running PHP 5.3 which has been declared end of life. Significant speed gains can be found by using the latest PHP 5.5 or 5.4. PHP 5.5 now has the Zend opcache built in which is a method that is used to significantly speed up PHP requests through code caching.

On some hosts with cPanel, upgrading PHP is a simple matter of going to Advanced >> PHP Configuration and changing the default PHP to 5.5. Note that after upgrading you will need to check your websites functionality as upgrades can sometimes cause problems.

#23. Use the latest WordPress

WordPress is constantly under development and new versions are released every few months. Usually new versions bring improvements such as speed boosts.

#24. Control Post Revisions

Every time you make a change to a post or page WordPress stores a revision copy just in case you need to go back to an old revision. By default WordPress stores ALL revisions you make. So if you edit your posts a lot there could be dozens of revisions taking up database space. I recommend you install the Revision Control plugin which will control the number of revisions kept. Set the number of revisions to how many you think you’ll need. In my case I chose to only keep 3 revisions at a time.

#25. Stop No-Referrer Comment Spam and Login Attacks

We can block spam bots and hackers brute forcing their way into the wp-login page with simple .htaccess file code. When a bot tried to access a page, it will usually try to access it directly without first visiting your site. If this happens we can detect it and block access to the bot with the .htaccess code below. Unfortunately, this isn’t effective as it used to be as modern advanced bots will get around this, but it will still stop many bots using simpler methods.

# Stop spam attack logins and comments
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
RewriteCond %{HTTP_REFERER} !.*YOUR_DOMAIN.com.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]
</IfModule>