Page autorefresh at source code changes

Did you get ever tired because of pressing all time F5 or Ctrl+R during the development cycle?

It doesn’t take a lot of time to do it manually. But think how many times you did it per hour, per day, per week? Every time you want to see the effect of you changes you need to switch between browser and your favorite IDE by pressing Alt+Tab in the best case or by using mouse for it. This tedious process can be simplified and minimised by installing no additional software/dependencies.  Most of ways to do it what I found demanded to install different IDEs, special tools or some other tricky methods.

Unfortunately I don’t have root access on all development machines what I use so I can’t afford me to follow above mentioned solutions. Moreover they have one big pitfall. They suit only if the development process goes in local environment. This is a debatable question that the development should never happen on remote host. Actually this is true. But this is not always the case. Sometimes you just can’t move to local environment. Either because of lack of budget or due to unreasonable proportion of time what you might spend fixing actual problem to the moving the project.

There must be an easier way. Yes, it is. All you need is to include a single javascript file – smart_reloader.js  into page what you want to update and to copy a php file – smart_reloader.php into root folder.

That’s all.The source code of smart_reloader.js

/* 
 *   Feb 7, 2015   11:18:58 PM 
 *   @copyright (c) 2015,  Alex Shulzhenko,  contact@alexshulzhenko.ru
 *   @license GPL 3.0, http://opensource.org/licenses/GPL-3.0
 *
 */

/**
 * Sends request to check files for updates
 * @return  - ignored
 */
(function () {
    /**
     * @constant  - Change this value if you are not satisfied with default
     *     Setting smaller number will cause requests to be send more often but
     *     in the same time page will be realoded faster
     * @type {Number} how often to check for changes - in seconds
     */ 
    var UPDATE_INTERVAL = 1000;

    var path = location.origin + '/smart_reloader.php',
            last_value = 0;

    var timer = setInterval(function () {
        jQuery.post(path, {}, function (result) {

            if (!jQuery.isNumeric(result)) {
                clearInterval(timer);
                alert('Error happened, check logs');
                console.log(result);
            }

            if (result != last_value && last_value != 0) {
                location.reload();
            } else {
                last_value = result;
            }

        }).fail(function (xhr, textStatus, errorThrown) {
            clearInterval(timer);
            location.reload();
//            alert(path + " fail, check path to the php script");
            console.log(xhr.responseText);
            console.log(textStatus);
            console.log(errorThrown);
        });
    }, UPDATE_INTERVAL);
})();

The source code of smart_reloader.php

/*
 *   Feb 3, 2015   9:50:18 PM
 *   @copyright (c) 2015,  Alex Shulzhenko,  contact@alexshulzhenko.ru
 *   @license GPL 3.0, http://opensource.org/licenses/GPL-3.0
 * 
 *   Builds list of files which should be watched
 */


/**
 * Specify extensions of files what you want to watch
 * @var String[]
 * 
 */
$extensions = array('js', 'css','php');

/**
 * Specify here the  directories which you want to watch, the more exact directory specified the better 
 * 
 * @var String[] - container 
 */
$dirs_to_watch = array('wp-content');


$files = get_list_of_files($dirs_to_watch, $extensions);
$total_time = check_for_changes($files);

echo $total_time;

/**
 *  returns formed list of all files with specified extensions
 * @param type $path
 */
function get_list_of_files($dirs_to_watch, $extensions = false)
{
    $full_list = [];
    $pattern = '';

    if ($extensions)
    {
        $pattern = '/^';

        foreach ($extensions as $elem)
        {
            $pattern .= '.+\.' . $elem . '|';
        }
        // trim last | symbol
        if (count($extensions) > 1)
        {
            $pattern = substr($pattern, 0, strlen($pattern) - 1);
        }

        $pattern .= '$/i';
    }
    else
    {
        return array(-1, "no extensions were specified");
    }


    foreach ($dirs_to_watch as $dir)
    {
        $directory = new RecursiveDirectoryIterator($dir);
        $iterator = new RecursiveIteratorIterator($directory);
        $filtered = new RegexIterator($iterator, $pattern, RecursiveRegexIterator::GET_MATCH);

        $arr = iterator_to_array($filtered, false);

        foreach ($arr as $value)
        {
            $full_list[] = $value[0];
        }
    }
    return $full_list;
}

/**
 * Checks for changes
 * @param array $list_of_files  list of files to be checked
 * @return int   total time 
 */
function check_for_changes($list_of_files)
{
    $sum = 0;
    foreach ($list_of_files as $elem)
    {
        clearstatcache($elem);
        
      // as practice showed this shoudn't be optimised  
        if (file_exists($elem))
        {
            $last_modified = filemtime($elem);

            if ($last_modified)
            {
                $sum+= $last_modified;
            }
        }
    }
    return $sum;
}

Alternatively you can download file responsive for server’s part manually and use ready js files hosted at CDN. To get server’s part you should follow the link above. To include javascript file you can use any of the links:

All these javascript files are the same except how often they poll system to check for changes. E.g. the first one smart_reloader_1.js will poll every second and the last one will poll every 15th second. Of course you are free to change interval to whatever you like although my personal experience has proven that 1 second delay fits the best. As you may see this project boils down to polling file system for changes and you may mind that it consumes more CPU/Disk resources. Sure.  But updating  the page manually consumes your resource. Let your computer do the job for you. This is main point of programming, isn’t it?

Smart_reloader.php file has settings in the top of file where you can specify what directories it should watch. It’s highly recommended to limit it only to certain directories which contain js or css files what you modify during your workflow process if you care about performance, of course.

Minimal test version is hosted at Bitbucket as SmartReloaderSh.



Comments
David
April 12, 2015 at 18:12

Why not just use livereload?

Alex Shulzhenko
April 16, 2015 at 18:44

There are many reasons for that. Some of them are: this is an additional software, not everybody has Mac or Windows (I don’t have), I’ve been using Netbeans and vim for years and got used for them a lot and wouldn’t like to switch to another editor.

Breta
February 7, 2016 at 14:15

Thanks for your smart page reloader script. Really good idea. It is simple, no dependencies, yet powerfull.

ling
September 15, 2016 at 08:05

Excellent! Would be even better without jquery dependency.


Leave a Reply

Your email address will not be published. Required fields are marked *