Skip to content

Instantly share code, notes, and snippets.

@mikeckennedy
Last active August 20, 2023 18:55
Show Gist options
  • Select an option

  • Save mikeckennedy/4b64418d9cd4872a7b54d7d69b5b2cde to your computer and use it in GitHub Desktop.

Select an option

Save mikeckennedy/4b64418d9cd4872a7b54d7d69b5b2cde to your computer and use it in GitHub Desktop.

Revisions

  1. mikeckennedy revised this gist Aug 19, 2023. 1 changed file with 33 additions and 7 deletions.
    40 changes: 33 additions & 7 deletions server-hot-reload.js
    Original file line number Diff line number Diff line change
    @@ -1,18 +1,27 @@
    // *************************************************************************
    // server-hot-reload.js v1.0.5
    //
    // Server-side hot reload check by Michael Kennedy (https://mkennedy.codes).
    // Released under the MIT open source license, 2023.
    //
    // Usage: Include this file in your "application shell" layout template
    // or directly into any page you'd like to check.
    // When the contents of the page change in any way, the page will be reloaded.
    //
    // Usage:
    //
    // Set the checkIntervalInMs time to the frequency you need. Usually 1 sec
    // should be fine, but if a page is slow maybe increase the delay.
    // * Include this file in your "application shell" layout template
    // or directly into any page you'd like to check.
    //
    // When the contents of the page change in any way, the page will be reloaded.
    // * Call toggleServerReload() within the browser console to pause/resume
    // when you want it to give your server a break. Useful when you want to
    // step through breakpoints and don't want the noise, etc.
    //
    // * Set the checkIntervalInMs time to the frequency you need. Usually 1 sec
    // should be fine, but if a page is slow maybe increase the delay.
    //

    let currentPageHash = "UNKNOWN";
    let checkIntervalInMs = 1000;
    let active = true;

    // *************************************************************************
    // When the doc is ready, we'll start checking for changes.
    @@ -24,12 +33,17 @@ document.addEventListener("DOMContentLoaded", function () {
    setInterval(() => downloadHtml(url).then(reloadIfNecessary), checkIntervalInMs);
    });


    // *************************************************************************
    // Called on every page content check (interval is checkIntervalInMs milliseconds).
    //
    function reloadIfNecessary(html) {
    if (!active) {
    return;
    }

    if (html == null || html.length === 0) {
    console.log("Something went wrong with server hotreload check... Trying again at interval.")
    console.log("Something went wrong with server hot-reload check... Trying again at interval.")
    return
    }

    @@ -50,6 +64,14 @@ function reloadIfNecessary(html) {
    window.location.reload();
    }

    // noinspection JSUnusedGlobalSymbols
    function toggleServerReload() {
    active = !active;
    const msg = "Server hot reload is now " + (active ? "ACTIVE" : "PAUSED") + ".";
    //console.log("Server hot reload is now " + (active ? "active" : "paused") + ".");
    return msg;
    }

    function hashCode(html) {
    let hash = 0, i, chr;
    if (html.length === 0) return hash;
    @@ -62,6 +84,10 @@ function hashCode(html) {
    }

    async function downloadHtml(url) {
    if (!active) {
    return null;
    }

    const thisURL = new URL(url)
    thisURL.searchParams.append('server_hot_reload_check', 'true')
    try {
    @@ -70,4 +96,4 @@ async function downloadHtml(url) {
    } catch (e) {
    return '';
    }
    }
    }
  2. mikeckennedy revised this gist Aug 18, 2023. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions server-hot-reload.js
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,6 @@

    let currentPageHash = "UNKNOWN";
    let checkIntervalInMs = 1000;
    let setIntervalInstance;

    // *************************************************************************
    // When the doc is ready, we'll start checking for changes.
    @@ -22,7 +21,7 @@ document.addEventListener("DOMContentLoaded", function () {
    console.log("Server hot reload active at " + new Date().toLocaleTimeString() + ". Watching for changes ...");
    const url = document.location.href;

    setIntervalInstance = setInterval(() => downloadHtml(url).then(reloadIfNecessary), checkIntervalInMs);
    setInterval(() => downloadHtml(url).then(reloadIfNecessary), checkIntervalInMs);
    });

    // *************************************************************************
  3. mikeckennedy revised this gist Aug 18, 2023. 1 changed file with 21 additions and 43 deletions.
    64 changes: 21 additions & 43 deletions server-hot-reload.js
    Original file line number Diff line number Diff line change
    @@ -13,6 +13,7 @@

    let currentPageHash = "UNKNOWN";
    let checkIntervalInMs = 1000;
    let setIntervalInstance;

    // *************************************************************************
    // When the doc is ready, we'll start checking for changes.
    @@ -21,14 +22,20 @@ document.addEventListener("DOMContentLoaded", function () {
    console.log("Server hot reload active at " + new Date().toLocaleTimeString() + ". Watching for changes ...");
    const url = document.location.href;

    setInterval(() => downloadHtml(url, reloadIfNecessary), checkIntervalInMs);
    setIntervalInstance = setInterval(() => downloadHtml(url).then(reloadIfNecessary), checkIntervalInMs);
    });

    // *************************************************************************
    // Called on every page content check (interval is checkIntervalInMs milliseconds).
    //
    function reloadIfNecessary(html) {
    const newHash = html.hashCode();
    if (html == null || html.length === 0) {
    console.log("Something went wrong with server hotreload check... Trying again at interval.")
    return
    }

    const newHash = hashCode(html);
    if (!newHash) return;
    if (currentPageHash === "UNKNOWN") {
    // Compute the hash since have never seen this response on this URL before (first run).
    currentPageHash = newHash;
    @@ -44,53 +51,24 @@ function reloadIfNecessary(html) {
    window.location.reload();
    }


    // *************************************************************************
    // Utility functions (downloads, hashing, etc.)
    //
    function makeHttpObject() {
    try {
    return new XMLHttpRequest();
    } catch (error) {
    }
    try {
    return new ActiveXObject("Msxml2.XMLHTTP");
    } catch (error) {
    }
    try {
    return new ActiveXObject("Microsoft.XMLHTTP");
    } catch (error) {
    }

    throw new Error("Could not create HTTP request object.");
    }

    String.prototype.hashCode = function () {
    function hashCode(html) {
    let hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i);
    if (html.length === 0) return hash;
    for (i = 0; i < html.length; i++) {
    chr = html.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
    }
    return hash;
    }

    function downloadHtml(url, callback_func) {
    if (url.includes('?')) {
    url += "&server_hot_reload_check=true";
    } else {
    url += "?server_hot_reload_check=true";
    async function downloadHtml(url) {
    const thisURL = new URL(url)
    thisURL.searchParams.append('server_hot_reload_check', 'true')
    try {
    const request = await fetch(thisURL);
    return request.text();
    } catch (e) {
    return '';
    }

    const request = makeHttpObject();
    request.open("GET", url, true);
    request.send(null);
    request.onreadystatechange = function () {
    if (request.readyState === 4) {
    // console.log("PAGE IS: ");
    // console.log(request.responseText);
    callback_func(request.responseText);
    }
    };
    }
  4. mikeckennedy revised this gist Aug 18, 2023. No changes.
  5. mikeckennedy created this gist Aug 18, 2023.
    96 changes: 96 additions & 0 deletions server-hot-reload.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    // *************************************************************************
    // Server-side hot reload check by Michael Kennedy (https://mkennedy.codes).
    // Released under the MIT open source license, 2023.
    //
    // Usage: Include this file in your "application shell" layout template
    // or directly into any page you'd like to check.
    //
    // Set the checkIntervalInMs time to the frequency you need. Usually 1 sec
    // should be fine, but if a page is slow maybe increase the delay.
    //
    // When the contents of the page change in any way, the page will be reloaded.
    //

    let currentPageHash = "UNKNOWN";
    let checkIntervalInMs = 1000;

    // *************************************************************************
    // When the doc is ready, we'll start checking for changes.
    //
    document.addEventListener("DOMContentLoaded", function () {
    console.log("Server hot reload active at " + new Date().toLocaleTimeString() + ". Watching for changes ...");
    const url = document.location.href;

    setInterval(() => downloadHtml(url, reloadIfNecessary), checkIntervalInMs);
    });

    // *************************************************************************
    // Called on every page content check (interval is checkIntervalInMs milliseconds).
    //
    function reloadIfNecessary(html) {
    const newHash = html.hashCode();
    if (currentPageHash === "UNKNOWN") {
    // Compute the hash since have never seen this response on this URL before (first run).
    currentPageHash = newHash;
    return;
    }

    if (newHash === currentPageHash) {
    return;
    }

    // Something, somewhere in the page has changed. Reload
    console.log("Page change detected, reloading now!")
    window.location.reload();
    }


    // *************************************************************************
    // Utility functions (downloads, hashing, etc.)
    //
    function makeHttpObject() {
    try {
    return new XMLHttpRequest();
    } catch (error) {
    }
    try {
    return new ActiveXObject("Msxml2.XMLHTTP");
    } catch (error) {
    }
    try {
    return new ActiveXObject("Microsoft.XMLHTTP");
    } catch (error) {
    }

    throw new Error("Could not create HTTP request object.");
    }

    String.prototype.hashCode = function () {
    let hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
    }
    return hash;
    }

    function downloadHtml(url, callback_func) {
    if (url.includes('?')) {
    url += "&server_hot_reload_check=true";
    } else {
    url += "?server_hot_reload_check=true";
    }

    const request = makeHttpObject();
    request.open("GET", url, true);
    request.send(null);
    request.onreadystatechange = function () {
    if (request.readyState === 4) {
    // console.log("PAGE IS: ");
    // console.log(request.responseText);
    callback_func(request.responseText);
    }
    };
    }