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

javascript caching versioning

399197 просмотра

23 ответа

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

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

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

Автор: AdamB Источник Размещён: 17.05.2019 02:54

Ответы (23)


479 плюса

Решение

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

Например:

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

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

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

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

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

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

Автор: Huppie Размещён: 28.08.2008 02:34

79 плюса

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

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

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

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

Cache-Control: no-cache, must-revalidate
Автор: Chase Seibert Размещён: 17.09.2008 04:04

42 плюса

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 . Когда вы меняете версию, клиентский браузер обновит новый файл.

Автор: Hắc Huyền Minh Размещён: 06.10.2011 08:13

32 плюса

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

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

Автор: amos Размещён: 14.08.2014 08:05

25 плюса

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

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

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

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

Автор: Erik Corona Размещён: 02.12.2015 12:45

18 плюса

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

Поэтому вместо того stuff.js?123, я сделалstuff_123.js

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

Автор: Echo Размещён: 17.09.2008 04:08

10 плюса

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

Автор: Ravi Ram Размещён: 23.01.2014 01:10

5 плюса

Для 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();
    }
    ...
}
Автор: Ivan Kochurkin Размещён: 03.08.2013 01:55

4 плюса

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

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

Автор: Pazu Размещён: 17.09.2008 04:03

3 плюса

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

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

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

Автор: Aman Singh Размещён: 08.11.2017 08:27

2 плюса

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

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

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

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

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

Автор: Michael Franz Размещён: 10.10.2015 08:53

1 плюс

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

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

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

Автор: Richard Turner Размещён: 17.09.2008 02:31

1 плюс

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

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

Автор: Derek Adair Размещён: 27.11.2010 09:00

1 плюс

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

Автор: AdamB Размещён: 28.08.2008 02:42

1 плюс

Несмотря на то, что это специфический для фреймворка, Django 1.4 имеет эту функцию, которая работает аналогично ссылке на сайт «greenfelt» в ответе выше.

Автор: Taras Размещён: 06.10.2012 06:26

1 плюс

В 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последнее изменение

Автор: user1944129 Размещён: 03.02.2013 11:48

1 плюс

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

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

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

Автор: ccherwin Размещён: 29.06.2017 10:30

1 плюс

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

Например,

поставщик. a7561fb0e9a071baadb9 .js
main. b746e3eb72875af2caa9 .js

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

Автор: schrodinger's code Размещён: 27.09.2018 11:00

0 плюса

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

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

Автор: pcorcoran Размещён: 17.09.2008 03:55

0 плюса

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

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

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

Автор: Willabee Размещён: 13.05.2009 12:00

0 плюса

Один простой способ. Изменить 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]
Автор: Goran Siriev Размещён: 06.01.2017 08:41

0 плюса

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

<script src="~/JsFilePath/JsFile.js?v=@DateTime.UtcNow.ToString()"></script>
Автор: dragonal Размещён: 11.12.2018 09:29

0 плюса

Ниже работало для меня:

<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" />`enter code here`
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
</head>
Автор: H.Ostwal Размещён: 01.03.2019 09:38
Вопросы из категории :
32x32