Как заставить клиентов обновлять файлы JavaScript?

в настоящее время мы работаем в частной бета-версии и поэтому все еще находимся в процессе внесения довольно быстрых изменений, хотя, очевидно, что по мере увеличения использования мы будем замедлять этот процесс. При этом одна из проблем, с которой мы сталкиваемся, заключается в том, что после того, как мы выталкиваем обновление с новыми файлами JavaScript, клиентские браузеры все еще используют кэшированную версию файла, и они не видят обновления. Очевидно, что по вызову поддержки мы можем просто сообщить им, чтобы сделать ctrlФ5 обновить, чтобы убедиться, что они получают обновленные файлы с сервера, но было бы предпочтительнее обработать это до этого времени.

наша текущая мысль заключается в том, чтобы просто прикрепить номер версии к имени файлов JavaScript, а затем, когда будут внесены изменения, увеличить версию скрипта и обновить все ссылки. Это определенно делает работу, но обновление ссылок на каждый выпуск может стать громоздким.

As Я уверен, что мы не первые, кто разбирается с этим, я решил, что выброшу это в сообщество. Как вы обеспечиваете обновление кэша клиентов при обновлении кода? Если вы используете метод, описанный выше, используете ли вы процесс, который упрощает изменение?

21 ответов


насколько я знаю, общим решением является добавление ?<version> к src-ссылке скрипта.

например:

<script type="text/javascript" src="myfile.js?1500"></script>

Я предполагаю, что на данный момент нет лучшего способа, чем найти-заменить, чтобы увеличить эти "номера версий" во всех тегах скрипта?

у вас может быть система управления версиями сделать это для вас? Большинство систем управления версиями имеют возможность автоматически вводить номер редакции при регистрации для пример.

Это будет выглядеть примерно так:

<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>

конечно, всегда есть лучшие решения как этот.


добавление текущего времени к URL-адресу действительно является распространенным решением. Однако, вы также можете управлять этим на уровне веб-сервера, если вы хотите. Сервер может быть настроен для отправки различных заголовков HTTP для файлов javascript.

например, чтобы заставить файл кэшироваться не более 1 дня, вы должны отправить:

Cache-Control: max-age=86400, must-revalidate

для бета-версии, если вы хотите заставить пользователя всегда получать последнюю версию, вы бы использовали:

Cache-Control: no-cache, must-revalidate

Google Page-Speed: не включайте строку запроса в URL для статических ресурсов. Большинство прокси, особенно Squid до версии 3.0, не кэшируют ресурсы с помощью"?"в их URL, даже если в ответе присутствует заголовок Cache-control: public. Чтобы включить кэширование прокси для этих ресурсов, удалите строки запроса из ссылок на статические ресурсы и вместо этого Закодируйте параметры в имена файлов.

в этом случае, вы можете включить версию в URL ex:http://abc.com/v1.2/script.js и используйте apache mod_rewrite для перенаправления ссылки наhttp://abc.com/script.js. При изменении версии браузер клиента обновит новый файл.


этот ответ опоздал всего на 6 лет, но я не вижу этого ответа во многих местах... В HTML5 ввела Кэш Приложения, который используется для решения этой проблемы. Я обнаружил, что новый серверный код, который я писал, разрушал старый javascript, хранящийся в браузерах людей, поэтому я хотел найти способ истечь их javascript. Используйте файл манифеста, который выглядит следующим образом:

CACHE MANIFEST
# Aug 14, 2014
/mycode.js

NETWORK:
*

и генерировать этот файл с новой отметкой времени каждый раз, когда вы хотите, чтобы пользователи обновляли их кэш. В качестве примечания, если вы добавите это, браузер будет не перезагрузка (даже когда пользователь обновляет страницу), пока манифест говорит он.


Как насчет добавления файла в качестве параметра нагрузки?

<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>

поэтому каждый раз, когда вы обновляете файл, параметр "filever" изменяется.

Как насчет того, когда вы обновляете файл и ваши результаты обновления в том же размере файла? каковы шансы?


не все браузеры кэшируют файлы с '?' в нем. Что я сделал, чтобы убедиться, что он был кэширован как можно больше, я включил версию в имя файла.

так вместо stuff.js?123, Я stuff_123.js

Я mod_redirect(Я думаю) в apache to have stuff_*.js нужно stuff.js


для ASP.NET страницы я использую следующее

до

<script src="/Scripts/pages/common.js" type="text/javascript"></script>

после (перезагрузка)

<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

добавление DateTime.Сейчас.Клещи работают очень хорошо.


для ASP.NET я полагаю, что следующее решение с расширенными параметрами (режим отладки / выпуска, версии):

JS или Css файлы, включенные таким образом:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

глобальные.JsPostfix и глобальный.CssPostfix рассчитывается следующим образом в Global.асакс:

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}

Если вы создаете страницу, которая ссылается на файлы JS, простое решение добавляет метку времени последнего изменения файла к сгенерированным ссылкам.

Это очень похоже на ответ Huppie, но работает в системах управления версиями без замены ключевых слов. Это также лучше, чем добавить текущее время, так как это предотвратит кэширование, даже если файл вообще не изменится.


функция jQuery getScript также может использоваться для обеспечения загрузки JS-файла при каждой загрузке страницы.

вот как я это сделал:

$(document).ready(function(){
    $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
         startProgram();
    });
});

Проверьте функцию вhttp://api.jquery.com/jQuery.getScript/

по умолчанию $.getScript () устанавливает для параметра кэша значение false. Это добавляет параметр запроса с отметкой времени к URL-адресу запроса, чтобы убедиться, что браузер загружает сценарий каждый раз, когда он запрашивается.


мы создаем SaaS для пользователей и предоставления им сценарий, чтобы вложить в их сайте страницу, и невозможно было прикрепить версия со скриптом, как пользователь будет прикрепить скрипт к своему сайту для приложений, и я не могу заставить их изменить версию каждый раз обновлять скрипт

Итак, мы нашли способ, чтобы загрузить новую версию скрипта каждый раз, когда пользователь вызывает скрипт

ссылка сценария для

<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>

скрипт файл

if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
   init();
} else {
   loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}

var loadscript = function(scriptURL) {
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = scriptURL;
   head.appendChild(script);
}

var guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

var init = function() {
    // our main code
}

объяснение:

пользователь прикрепил скрипт, предоставленный им на своем веб-сайте, и мы проверили наличие уникального токена, прикрепленного к скрипту, существует или нет с помощью селектора jQuery, а если нет, то загрузите его динамически с новым токеном (или версией)

это вызов одного и того же скрипта дважды, что может быть проблемой производительности, но это действительно решает проблему заставить скрипт не загружаться из кэша, не помещая версию в фактическую ссылку скрипта, предоставленную пользователю или клиенту

Предупреждение: Не используйте, если производительность является большой проблемой в вашем случае.


использовать версию GET переменная для предотвращения кэширования браузера.

добавление ?v=AUTO_INCREMENT_VERSION до конца вашего url предотвращает кэширование браузера-избегая любых и всех кэшированных сценариев.


мой коллега только что нашел ссылку на этот метод сразу после того, как я опубликовал (в ссылке на css) в http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/. Приятно видеть, что другие используют его, и он, похоже, работает. Я предполагаю, что на данный момент нет лучшего способа, чем найти-заменить, чтобы увеличить эти "номера версий" во всех тегах скрипта?


хотя это специфичный фреймворк, Django 1.4 имеет этот functionailty который работает аналогично ссылке на сайт "greenfelt" в ответ выше


на PHP:

function latest_version($file_name){
    echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}

на HTML-код:

<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>

как работает:

в HTML напишите filepath и имя, как вы делаете, но только в функции. PHP получает filetime файла и возвращает filepath+name+"?"+time последние изменения


перебор кэша ASP.NET Core через tag helper обработает это для вас и позволит вашему браузеру хранить кэшированные скрипты/css до тех пор, пока файл не изменится. Просто добавьте тег helper asp-append-version= "true" в свой скрипт (js) или ссылку (css):

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>

Дэйв Пакетт имеет хороший пример и объяснение перебора кэша здесь (внизу страницы) Кэш Перебора


одним из решений является добавление строки запроса с меткой времени в URL-адрес при извлечении ресурса. Это использует тот факт, что браузер не будет кэшировать ресурсы, извлеченные из URL-адресов со строками запросов в них.

вы, вероятно, не хотите, чтобы браузер вообще не кэшировал эти ресурсы; более вероятно, что вы хотите, чтобы они кэшировались, но вы хотите, чтобы браузер получал новую версию файла, когда он станет доступным.

наиболее распространенные решение добавьте метку или номер версии в имя файла. Это немного больше работы, потому что ваш код должен быть изменен, чтобы запросить нужные файлы, но это означает, что, например, версию 7 snazzy_javascript_file.js (т. е. snazzy_javascript_file_7.js) кэшируется в браузере до выпуска версии 8, а затем ваш код изменяется на fetch snazzy_javascript_file_8.js вместо.


простое решение? Не позволяйте кэш браузера вообще. Добавлять текущее время (в МС) в качестве запроса.

(вы все еще находитесь в бета-версии, поэтому вы можете обоснованно не оптимизировать производительность. Но YMMV здесь.)


преимущества использования file.js?V=1 на fileV1.js это то, что вам не нужно хранить несколько версий файлов JavaScript на сервере.

беда, которую я вижу с file.js?V=1 возможно, у вас есть зависимый код в другом файле JavaScript, который ломается при использовании новой версии утилит библиотеки.

ради обратной совместимости, я думаю, что гораздо лучше использовать jQuery.1.3.js для ваших новых страниц и пусть существующие страницы используют jQuery.1.1.js, пока вы не готова обновить старые страницы, если это необходимо.


один простой способ. Редактировать htaccess файл

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]

в настоящее время распространенной практикой является создание хэш-кода содержимого как части имени файла, чтобы заставить браузер, особенно IE, перезагрузить файлы javascript или css-файлы.

например,

поставщика.a7561fb0e9a071baadb9.js
главный.b746e3eb72875af2caa9.js

обычно это задание для инструментов сборки, таких как webpack. Вот еще подробности если кто хочет попробовать, если вы используете webpack.