Preventing jQuery from cache busting resources loa

2019-02-19 06:32发布

问题:

Using jQuery 1.7.1, I am loading some HTML fragments via AJAX that are injected into the DOM via the html() method.

The HTML content itself cannot be cached, but it may load some JavaScript resources that can be cached.

What I've found is when I disable caching in the $.ajax call, this adds the cache busting parameter to all HTTP requests made from jQuery as the HTML is injected into the DOM. This prevents the browser from caching the otherwise static JavaScript resources.

My current solution isn't very graceful and seems racy at that. I basically flip the global cache option after the AJAX call has succeeded, but before the HTML is processed.

var $dynamic = $('#dynamic');
$.ajax({
          url: href,
          cache: false,
          dataType: 'html',
          success: function(data, textStatus, jqXHR) {
              // This is hokey, but needed to allow browser to cache
              // resources loaded by the fragment
              $.ajaxSetup({cache:true});
              $dynamic.empty().html(data);
              $.ajaxSetup({});
          }
});

Can anyone think of a better way to do this? Should I avoid using the <script rel=...> tag in the AJAX-loaded fragment and use something else to get the JavaScript loaded?

Side note, there seem to be some related SO questions, but one of them has an accepted answer that's not an answer and another claims the behavior was changed in jQuery 1.4, so maybe this is a regression of some sort.

EDIT

To elaborate, the above jQuery snippet is applied to a div element. Trimmed down to something like this:

<html>
  <head>
      // ... load jquery ... 

      <script type="text/javascript">
         $(document).ready(function() {
            var $dynamic = $('#dynamic');
            $('a').click(function(e) {
                e.preventDefault();

                var $a = $(this);
                var href = $a.attr('href');
                $.ajax({
                    url: href,
                    cache: false,
                    dataType: 'html',
                    success: function(data, textStatus, jqXHR) {
                        $.ajaxSetup({cache:true});
                        $dynamic.empty().html(data);
                        $.ajaxSetup({});
                    } 
                });
            });
         });
      </script>
  </head>
  <body>
      <a href="/api/dynamic-content/">Click Here</a>
      <div id="dynamic"></div>
  </body>
</html>

When the event occurs, in this case a click, the handler invokes $.ajax to load a text/html fragment into the #dynamic div element. Here's an example of what such a fragment could look like:

<p>Some dynamic content here...</p>
<script type="text/javascript" src="/static/some.js"></script>

So the success handler of the AJAX call loads the text/html snippet and injects it into the DOM via the jQuery html(...) function. As you can see, the text/html fragment may also have a link to an external script.

The documentation for html(...) indicates that this usage pattern is just fine and that the script resources will be loaded and executed as one would expect.

The problem I'm having is that the content of the text/html fragment is not cacheable and must be invoked with the cache-busting mechanism. However, the JavaScript resource that it needs to load is static and cacheable, but jQuery applies cache-busting when loading the JS resource because the initial AJAX call was made with cache : false

Broken down, here's the chain of events:

  • Click handler invoked
  • AJAX function performs HTTP GET /api/dynamic-content/?_=1331829184164
  • Success handler calls $dynamic.empty().html(data);
  • $dynamic.empty().html(...) performs HTTP GET /static/some.js?_=1331829184859

I'm looking for a more elegant way to disable the cache-busting on the subsequent or 'inner' HTTP request that's triggered to load the JS resource when the text/html fragment gets injected into the DOM.

In short, everything else is correct, I just want it to do HTTP GET /static/some.js, not HTTP GET /static/some.js?_=1331829184859 on that final step.

回答1:

If your server is set up to correctly identify which resources can and cannot be cached, then the cache: false option should not be necessary.

Another alternative is to use a POST rather than a GET using the type: 'POST' option on the ajax method.