NOTE: You are viewing documentation for the MoovJS/Adapt version of the Moovweb SDK
View documentation for next-gen Moovweb XDN & PWA framework
Moovweb | moov_cache.js
Menu Developer Moovweb University

moov_cache.js

/**
 * A namespace containing methods for caching purposes.
 * @namespace cache
 */

'use strict';

function Cache(fns,selector,env) {
    this.export = fns.export;
    this.selector = selector;
    this.path = (env === undefined) ? '/' : env.path;
}

/**
 * @method enable
 * @summary moov_cache
 * @memberof cache
 * @description Enables caching for the response, provided that the origin
 * response allows for caching.
 * @return {undefined} `undefined`
 * @example
 * let cache = new Cache(fns, $, env);
 * cache.enable();
 * // => Result: the response is cached if the desktop response is cached; or
 * //    caching is ignored if the desktop response is not cached.
 */
Cache.prototype.enable = function() {
    this.export('Cache', 'true');
};

/**
 * @method enable_for
 * @summary moov_cache
 * @memberof cache
 * @description Enables caching for the response for a specified period of time,
 * provided that the origin response allows for caching.
 * @param {Number|String} seconds A number or string containing the number for
 * the amount of time in seconds for which to cache the response.
 * @return {undefined} `undefined`
 * @example
 * let cache = new Cache(fns, $, env);
 * cache.enable_for(3300);
 * // => Result: the response is cached for 3300 seconds (via the Cache-Time
 * //    header) if the desktop response is cached; or caching is ignored if the
 * //    desktop response is not cached.
 */
Cache.prototype.enable_for = function(seconds) {
    this.enable();
    this.export('Cache-Time', seconds);
};

/**
 * @method force
 * @summary moov_cache
 * @memberof cache
 * @description Enables caching for the response, regardless of whether the
 * origin response allows for caching.
 * @return {undefined} `undefined`
 * @example
 * let cache = new Cache(fns, $, env);
 * cache.force();
 * // => Result: the response is cached.
 */
Cache.prototype.force = function() {
    this.export('Cache', 'force');
};

/**
 * @method force
 * @summary moov_cache
 * @memberof cache
 * @description Enables caching for the response for a specified period of
 * time, regardless of whether the origin response allows for caching.
 * @param {Number|String} seconds A number or string containing the number for
 * the amount of time in seconds for which to force cache the repsonse.
 * @return {undefined} `undefined`
 * @example
 * let cache = new Cache(fns, $, env);
 * cache.force_for(3300);
 * // => Result: the response is cached for 3300 seconds (via the Cache-Time
 * //    header).
 */
Cache.prototype.force_for = function(seconds) {
    this.force();
    this.export('Cache-Time', seconds);
};

function dynamic_section(tag,selector) {
    selector('html').find(tag).each(function(i,elem) {
        let text = '<span data-cache-hold=' + (i+1) +'></span>';
        selector(elem).after(text);
        selector('cachebox').append(elem);
    });
}

/**
 * @method html
 * @summary moov_cache
 * @memberof cache
 * @description Sets up HTML responses so that content (matching a given
 * selector) passed in is fetched as needed, but still allows the remainder of
 * the HTML response to be cached. Works in conjunction with Moovweb's
 * cachify.js (client-side asset JavaScript library). Note: This functionality
 * is experimental.
 * @param {String} tag A string for a CSS selector representing the dynamic
 * elements on the page that need to be fetched.
 * @param {String} enc A string for the encoding, defaulted to "utf-8".
 * @return {undefined|Array} `undefined`, provided that the original page is
 * requested; or an array of strings for HTML elements to be re-fetched, if the
 * flagged re-fetching version of the page is requested (indicated by
 * a "_mw_cached_fragments=true" query parameter).
 * @example
 * // In index.js ("html" content-type conditional check)
 * const Cache = require("moov_cache");
 * let cache = new Cache(fns, $, env);
 * let cache_array = cache.html(".bing, .google", "utf-8");
 * let matcher = '_mw_cached_fragments=true';
 * if (env.path.indexOf(matcher) >= 0) {
 *   return { body: cache_array, htmlparsed: false };
 * }
 * // => HTML input:
 * //    <body>
 * //      <img class="google" src="http://www.google.com/img.jpeg" alt="selfie">
 * //      <img class="bing" src="http://www.bing.com/img.jpeg" alt="selfie">
 * //    </body>
 * // => HTML response output (original page):
 * //    <body>
 * //      <span data-cache-hold="1"></span>
 * //      <span data-cache-hold="2"></span>
 * //    </body>
 * // => HTML dynamic output (original page):
 * //    <body>
 * //      <img class="google" src="http://www.google.com/img.jpeg" alt="selfie">
 * //      <img class="bing" src="http://www.bing.com/img.jpeg" alt="selfie">
 * //    </body>
 * // => Returns (flagged re-fetch response):
 * //    [
 * //      "<img class=\"google\" src=\"http://www.google.com/img.jpeg\" alt=\"selfie\">",
 * //      "<img class=\"bing\" src=\"http://www.bing.com/img.jpeg\" alt=\"selfie\">"
 * //    ]
 */
Cache.prototype = function(tag,enc) {
    let self = this;

    // Set encoding
    let encoding;
    if (enc === undefined) {
        encoding = 'utf-8';
    } else {
        encoding = enc;
    }
    // Export encoding to env
    this.export('Content-Type-Charset',encoding);

    let matcher = '_mw_cached_fragments=true';

    // Add cachebox tag after </html>
    this.selector('html').after('<cachebox></cachebox>');

    // Call dynamic_section and put stuff tagged into cachebox
    if (tag !== undefined) {
        dynamic_section(tag,this.selector);
    }

    // Here we determine if we are doing a dynamic fragment hit, or just our cachable static hit
    if (this.path.indexOf(matcher) >= 0) {
        // This is a fragment/dynamic hit! Time to jsonify!
        let json_array = [];
        self.selector('cachebox').find(tag).each(function(i,elem) {
            json_array[i] = self.selector(elem).toString();
        });
        return JSON.stringify(json_array);
    } else {
        // This must be a static hit
        // If we have anything in the cache box, then we assume that they want to cache the static part.
        if (self.selector('cachebox').children().length > 0) {
            // This only happens if there is something to cache!
            this.force();
        }

        // Okay, no matter what, during a static hit, we want to delete everything in the cachebox.
        this.selector('cachebox').remove();
    }
};

module.exports = Cache;
Last updated Mon Feb 26 2018 22:51:20 GMT+0000 (UTC)