Jquery getScript caching

24,893

Solution 1

There is an error as of the date this question was posted where both Firefox and Chrome would state that a script is not being loaded from Cache when it indeed is. As of the date of this answer this issue still exists. The easiest way to test is to use console.log and send out a version number.

To cache a dynamically loaded script it it simply done by using the following code.

function onDemandScript ( url, callback ) {
    callback = (typeof callback != 'undefined') ? callback : {};

    $.ajax({
         type: "GET",
         url: url,
         success: callback,
         dataType: "script",
         cache: true
     });    
}

For development you should comment out cache: true.

Solution 2

First lets clarify what is means that the jQuery disables the caching.

When jQuery disables the cache is means that is force the file to be load it again by the browser with some kind of trick, eg by adding one extra random number as parameter at the end of the url.

When jQuery have enable the cache, is not force anything and let the cache that you have set on the header of this file. Which means that if you do not have set on the header of the files parameters to keep it on browser cache, the browser will try to load it again by some methods.

So with enable the cache by jQuery you must also have been set the correct cache headers on your static files to be keep on browser cache, or else browser may try to load them again.

For files that browser see the created date on header, then is connect to the server asking the header again, is compare it and if is not have change then is not load it again, but is make one call to the server.

For files that you have set the a max age, and not ask the server till that date, then the browser is direct load it from the cache if he finds it.

To summarize:
The cache:true is let the browser decide for the cache of this file from the header you send.
The cache:false is force the file to be load again.

Some relative to cache questions:
caching JavaScript files
IIS7 Cache-Control

Tthe inside code
The getScript() is calling the jQuery.get() witch is a shorthand Ajax function of

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

So by calling the getScript() you make an ajax call, and the jQuery did not keep any kind of cache of your files if this is what you think at the first place.

Custom function to load the sripts
If you do not won to make a global cache:true, and you need only some files to be loaded with cache:true, you can make a custom function as:

function getScriptCcd(url, callback)
{
    jQuery.ajax({
            type: "GET",
            url: url,
            success: callback,
            dataType: "script",
            cache: true
    });
};

This is not affected by the global cache parameter and is load the script files with out adding anything non-cache parameters at the end.

Solution 3

There's a better option actually, you can turn ON caching for certain requests, for example:

$.ajaxPrefilter(function( options ) {
  if ( options.type==='GET' && options.dataType ==='script' ) {
      options.cache=true;
  }
});

Solution 4

By default, $.getScript() sets the cache setting to false. This appends a timestamped query parameter to the request URL to ensure that the browser downloads the script each time it is requested.

jQuery doc site has a nice extension for not appending a timestamp to the request and bypass the cache:

jQuery.cachedScript = function( url, options ) {

  // Allow user to set any option except for dataType, cache, and url
  options = $.extend( options || {}, {
    dataType: "script",
    cache: true,
    url: url
  });


  // Use $.ajax() since it is more flexible than $.getScript
  // Return the jqXHR object so we can chain callbacks
  return jQuery.ajax( options );
};

// Usage
$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
  console.log( textStatus );
});

Source

Solution 5

I know this is an old post, and the existing answer is the real answer, but touching on Iscariot's concern IT REALLY IS CACHING (at least kinda sorta). This is just a quirk of firefox. Maybe this will prove useful to others who are confused by this quirk.

I tested this concept with a REALLY LARGE javascript file that defines google map polygons for the Idaho DOT district boundaries based on arrays of tens of thousands of latlons (the uncompressed file size is 2,806,257, but I run it through a compression process). Using the following javascript

// Grab polys if not already loaded
if (typeof(defaults.data.polys) === 'undefined') {
    /*$.getScript('/Scripts/ScriptMaster.php?file=Districts', function () {});*/
    $.ajax({
        type: "GET",
        url: '/Scripts/ScriptMaster.php?file=Districts',
        success: function() {
            defaults.data.polys = getPolys();
            data.polys = defaults.data.polys;
        },
        dataType: "script",
        cache: true
    });
}

and you can see the relevant php (you don't want the actual Districts.js file it would take too much space on this post, so here's ScriptMaster.php)

<?php
require_once('../settings.php');

if (!isset($_GET['file'])) die();
$file = $_GET['file'];
$doCache = $file == 'Districts';

header('Content-type: application/x-javascript');
if ($doCache) {
    // This is a luxury for loading Districts.js into cache to improve speed
    //  It is at the top because firefox still checks the server for
    //  headers even when it's already cached
    $expires = 7 * 60 * 60 * 24; // set cache control to expire in a week (this is not likely to change)
    header('Cache-Control: max-age='.$expires.', must-revalidate');
    header('Last-modified: Fri, 3 May 2013 10:12:37 GMT');
    header('Expires: '.gmdate('D, d M Y H:i:s', time() + $expires).'GMT');
    header('Pragma: public');
}

ob_start("compress");
require_once($file.".js");
ob_end_flush();

function compress($buffer) {
    global $doCache;
    if (DEV_MODE && !$doCache) return $buffer;
    /* remove comments */
        $buffer = preg_replace('/\/\/.+?$/m', '', preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer));
    /* remove tabs, spaces, new lines, etc. */
        $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
    /* remove unnecessary spaces */
        $buffer = str_replace(': ', ':', $buffer);
        $buffer = str_replace(' :', ':', $buffer);
        $buffer = str_replace(', ', ',', $buffer);
        $buffer = str_replace(' ,', ',', $buffer);
        $buffer = str_replace('; ', ';', $buffer);
        $buffer = str_replace(' ;', ';', $buffer);
        $buffer = str_replace('{ ', '{', $buffer);
        $buffer = str_replace(' {', '{', $buffer);
        $buffer = str_replace('} ', '}', $buffer);
        $buffer = str_replace(' }', '}', $buffer);

    if ($doCache) { header('Content-Length: '.strlen($buffer)); }

    return $buffer;
}
?>

It's important to note that calling php's header functions BEFORE the script even executes the string you're going to print as unlike chrome and possibly (probably, I'm just too lazy to check) other browsers firefox appears to make a ping to server to check for headers before using cache. Maybe with more research you could determine if this pertains to elements in as equally as it does with ajax (probably not).

So I did five test runs showing the load times for this script with ajax as stated in firebug. Here are the results

#results loading the script after clearing cache (yes those are seconds, not ms)
200 OK      4.89s
200 OK      4.9s
200 OK      5.11s
200 OK      5.78s
200 OK      5.14s

#results loading the page with control+r
200 OK      101ms
200 OK      214ms
200 OK      24ms
200 OK      196ms
200 OK      99ms
200 OK      109ms

#results loading the page again by navigating (not refreshing)
200 OK      18ms
200 OK      222ms
200 OK      117ms
200 OK      204ms
200 OK      19ms
200 OK      20ms

As you can see, my localhost server to web client connection is not the most consistent and my laptop specs are a little shabby (single core processor and all, it's a few years old too) BUT THE POINT is there is a significant drop in load time after the cache is loaded.

[Also in case anyone's curious without the compression script (not like tabs, spaces or new lines are wasted, it just has to be readable still) takes somewhere between 7-8 seconds to load, but I'm not going to do that five times]

So never fear, it really is caching. For smaller scripts that only take ms's to load you may not notice the difference in firefox, honestly; simply because it checks for headers from the server. I know this because of the load time change from moving those header functions from the end of the script to the start. If you have those functions after php goes through the string it takes longer to load.

Hope this helps!

Share:
24,893
Case
Author by

Case

I am an award winning game dev. I know a lot, but I am still learning. If I can help you just let me know. https://twitter.com/SoliaOnline https://solia.online

Updated on August 11, 2020

Comments

  • Case
    Case over 3 years

    By Default $.getScript() disables caching and you can use $.ajaxSetup and set caching to true. When testing if the script is actually cached with Firebug most of the time the script is coming back at 200 (Which means the script is a fresh copy) and one in maybe 20 or 30 times it will come back 304 (meaning it used a cached version). Why is it getting a new copy the vast majority of the time?

    $.ajaxSetup({
        cache: true
     });
    
     $.getScript( scriptFile );
    

    The files that getScript retrieves have not been edited and the requests are a page change apart.