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

StackOverflow https://stackoverflow.com/questions/32414

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

Например:

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

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

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

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

<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:Не включайте строку запроса в URL-адрес для статических ресурсов.Большинство прокси-серверов, в первую очередь Squid до версии 3.0, не кэшируют ресурсы с символом "?" в своем URL, даже если Cache-control:открытый заголовок присутствует в ответе.Чтобы включить прокси-кэширование для этих ресурсов, удалите строки запроса из ссылок на статические ресурсы и вместо этого закодируйте параметры в самих именах файлов.

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

Это использование устарело: https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache

Этот ответ запоздал всего на 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 для того, чтобы 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.Now.работает очень хорошо.

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

Файлы Js или Css, включенные таким способом:

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

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

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, но работает в системах контроля версий без замены ключевых слов.Это также лучше, чем добавлять текущее время, поскольку это предотвратило бы кэширование, даже если файл вообще не изменился.

Мы создавали 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 selector, и если нет, то динамически загружаем его с более новым токеном (или версией)

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

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

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

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

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

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

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

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

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

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

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

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

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

Несмотря на то, что это специфичный фреймворк, Django 1.4 имеет эта функция доступна который работает аналогично ссылке на сайт "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 с помощью помощника по тегам справится с этим за вас и позволит вашему браузеру сохранять кэшированные скрипты / css до тех пор, пока файл не изменится.Просто добавьте вспомогательный тег asp-append-version="true" к тегу вашего скрипта (js) или ссылки (css):

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

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

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

Например,

поставщик.a7561fb0e9a071baadb9.js
Главная.b746e3eb72875af2caa9.js

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

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

(Вы все еще находитесь в стадии бета-тестирования, поэтому можете привести разумные доводы в пользу отказа от оптимизации производительности.Но 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]

В asp.net mvc вы можете использовать @DateTime.UtcNow.toString() для получения номера версии файла js.Номер версии автоматически изменяется вместе с датой, и вы заставляете клиентский браузер автоматически обновлять js-файл.Я использую этот метод, и это хорошо работает.

<script src="~/JsFilePath/JsFile.js?v=@DateTime.UtcNow.ToString()"></script>

Это сработало для меня:

<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
</head>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top