web-dev-qa-db-ja.com

jquery getScriptキャッシング

デフォルトでは、$。getScript()はキャッシュを無効にし、$。ajaxSetupを使用してキャッシュをtrueに設定できます。スクリプトが実際にFirebugで実際にキャッシュされているかどうかをテストする場合、ほとんどの場合、スクリプトは200(つまり、スクリプトが新しいコピーであることを意味します)に戻り、おそらく20または30回に1回は304に戻ります(つまり、キャッシュされたバージョン)。ほとんどの場合、新しいコピーを取得するのはなぜですか?

$.ajaxSetup({
    cache: true
 });

 $.getScript( scriptFile );

GetScriptが取得するファイルは編集されておらず、リクエストはページの変更です。

28
Case

この質問が投稿された日付の時点で、FirefoxとChromeの両方で、スクリプトが実際にはキャッシュからロードされていないことが示されています。問題はまだ存在します。テストする最も簡単な方法は、console.logを使用してバージョン番号を送信することです。

動的にロードされたスクリプトをキャッシュするには、次のコードを使用するだけです。

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

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

開発の場合、キャッシュをコメントアウトする必要があります:true。

9
Case

まず、jQueryがキャッシングを無効にすることの意味を明確にしましょう。

JQueryがキャッシュを無効にする場合は、がブラウザによってファイルを再度ロードすることを強制することを意味しますURLの最後にパラメーターとして乱数を1つ追加するなど、何らかのトリックを使用します。

JQueryがキャッシュを有効にする場合は何も強制せず、ヘッダーに設定したキャッシュを許可しますこのファイルの。つまり、ブラウザのキャッシュに保持するためにファイルパラメータのヘッダーを設定していない場合、ブラウザはいくつかの方法で再度ロードしようとします。

したがって、jQueryによるキャッシュを有効にすることで、静的ファイルに正しいキャッシュヘッダーを設定してブラウザーのキャッシュに保持する必要があります。そうしないと、ブラウザーがそれらを再度ロードしようとする可能性があります。

ブラウザーでヘッダーに作成日が表示されているファイルの場合、サーバーに接続して再度ヘッダーを要求し、ヘッダーを比較し、変更がない場合は再度ロードせず、サーバーに1回呼び出します。

最大経過時間を設定していて、その日までサーバーに要求しないファイルの場合、ブラウザーはそれを見つけた場合、キャッシュから直接ロードします。

要約するには
_cache:true_を使用すると、送信したヘッダーからこのファイルのキャッシュをブラウザに決定させることができます。
_cache:false_は、ファイルを強制的に再度ロードします。

キャッシュの質問に関連するもの:
JavaScriptファイルのキャッシュ
IIS7キャッシュ制御

内側のコード
getScript()jQuery.get()を呼び出しています魔女は 略式のAjax関数 of

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

したがって、getScript()を呼び出すことでajax呼び出しが行われ、jQueryが最初に考えた場合、ファイルのキャッシュを保持しませんでした。

スクリプトをロードするカスタム関数
グローバルcache:trueを作成することに失敗せず、cache:trueでロードする必要があるのは一部のファイルのみである場合は、次のようにカスタム関数を作成できます。

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

これはグローバルキャッシュパラメーターの影響を受けず、最後に非キャッシュパラメーターを追加せずにスクリプトファイルを読み込みます。

25
Aristos

デフォルトでは、$。getScript()はキャッシュ設定をfalseに設定します。これにより、タイムスタンプ付きのクエリパラメータがリクエストURLに追加され、ブラウザがリクエストされるたびにスクリプトがダウンロードされるようになります。

jQuery docサイトには、リクエストにタイムスタンプを追加せず、キャッシュをバイパスするためのNice拡張があります。

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 );
});

ソース

2
gdoron

実際にはより良いオプションがあります。たとえば、特定のリクエストに対してキャッシュをオンにすることができます。

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

私はこれが古い投稿であることを知っており、既存の答えは本当の答えですが、Iscariotの懸念に触れていますIT REALLY IS CACHING(少なくともちょっとちょっと)これはただFirefoxの奇妙なところです。たぶん、これはこの癖に混乱している他の人に役立つでしょう。

私はこのコンセプトを、数万のlatlonの配列に基づいてアイダホDOT地区の境界のグーグルマップポリゴンを定義する非常に大きなjavascriptファイルでテストしました(非圧縮ファイルのサイズは2,806,257ですが、圧縮プロセスで実行しました)。次の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
    });
}

そして、あなたは関連するphpを見ることができます(あなたは実際のDistricts.jsファイルがこの投稿であまりにも多くのスペースを必要としないので、ここでは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;
}
?>

スクリプトが印刷する文字列を実行する前にphpのヘッダー関数を呼び出すことは、chromeとは異なり、おそらく他のブラウザーをチェックするのが面倒すぎます)とは異なることに注意してください。 firefoxは、キャッシュを使用する前にヘッダーを確認するためにサーバーにpingを実行するようです。さらに調査すると、これがajaxと同じように(おそらくそうではない)要素に関係するかどうかを判断できます。

そのため、Firebugで述べたように、このスクリプトの読み込み時間をajaxで示す5つのテスト実行を行いました。これが結果です

#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

ご覧のように、私のローカルホストサーバーからWebクライアントへの接続は最も一貫性がなく、ラップトップの仕様は少し粗末です(シングルコアプロセッサであり、すべて数年前のものです)しかし、ポイントはあります重要キャッシュがロードされた後のロード時間の減少。

[また、圧縮スクリプトなしで誰かが興味を持った場合(タブ、スペース、新しい行が無駄になるなど、それがまだ読める必要があります)の読み込みには7〜8秒かかりますが、5回は行いません。回]

だから恐れることはありません、それは本当にキャッシュです。 msだけをロードする小さなスクリプトの場合、正直に言うと、Firefoxの違いに気付かない場合があります。それは単にサーバーからのヘッダーをチェックするからです。これらのヘッダー関数をスクリプトの最後から最初に移動することによるロード時間の変更のため、これはわかっています。 PHPが文字列を通過した後にこれらの関数がある場合、ロードに時間がかかります。

お役に立てれば!

2
Assimilater

おそらく探しているのはgetScriptOnce関数です。基本的に、ファイルが既に正常にロードされていることがわかっている場合、そのような関数が呼び出されても、そのようなファイルは再度ロードされません。

そんな関数を書いてみました。 FirebugのNetwork tabまたはChrome dev toolsでテストできます。これにより、同じファイルが1回読み込まれるだけです。ファイルにコピーする必要があるのは、getScriptOnce関数とグローバル配列ScriptArray

var getScriptOnce = (function(url, callback) {
  var scriptArray = []; //array of urls
  return function (url, callback) {
      //the array doesn't have such url
      if (scriptArray.indexOf(url) === -1){
          if (typeof callback === 'function') {
              return $.getScript(url, function(script, textStatus, jqXHR) {
                  scriptArray.Push(url);
                  callback(script, textStatus, jqXHR);
              });
          } else {
              return $.getScript(url, function(){
                  scriptArray.Push(url);
              });
          }
      }
      //the file is already there, it does nothing
      //to support as of jQuery 1.5 methods .done().fail()
      else{
          return {
              done: function () {
                  return {
                      fail: function () {}
                  };
              }
          };
      }
  }
}());

/*#####################################################################*/
/*#####################################################################*/


//TEST - tries to load the same jQuery file twice
var jQueryURL = "https://code.jquery.com/jquery-3.2.1.js";
console.log("Tries to load #1");
getScriptOnce(jQueryURL, function(){
  console.log("Loaded successfully #1")
});

//waits 2 seconds and tries to load again
window.setTimeout(function(){
  console.log("Tries to load #2");
  getScriptOnce(jQueryURL, function(){
    console.log("Loaded successfully #2");
  });
}, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>