Как заставить клиентов обновить файлы JavaScript? - PullRequest
540 голосов
/ 28 августа 2008

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

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

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

Ответы [ 23 ]

490 голосов
/ 28 августа 2008

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

Например:

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

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

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

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

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

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

82 голосов
/ 17 сентября 2008

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

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

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

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

Cache-Control: no-cache, must-revalidate
42 голосов
/ 06 октября 2011

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

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

32 голосов
/ 15 августа 2014

Это использование было отменено: 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:
*

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

25 голосов
/ 02 декабря 2015

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

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

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

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

18 голосов
/ 17 сентября 2008

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

Так что вместо stuff.js?123 я сделал stuff_123.js

Я использовал mod_redirect (я думаю) в apache для have stuff_*.js, чтобы перейти stuff.js

11 голосов
/ 23 января 2014

Для страниц 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.Ticks работает очень хорошо.

6 голосов
/ 03 августа 2013

Для 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();
    }
    ...
}
4 голосов
/ 17 сентября 2008

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

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

3 голосов
/ 08 ноября 2017

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

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

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

...