Почему клиент не получает новые версии этого скрипта в общей папке?
В моем проекте есть общая папка и скрипт внутри нее: public/worker.js
, который содержит кусок кода:
alert('foo');
Я называю этот скрипт с помощью Worker:
new Worker('worker.js');
Я запускаю Meteor и подключаюсь к своему приложению. foo
предупрежден.
Если я изменю public/worker.js
код для чего-либо еще:
alert('bar');
Сервер обновляет клиентов, клиент обновляет страницу, но не получает новый код, а использует старый (оповещение foo
вместо новой блестящей bar
). Очистка кэша с последующим обновлением устраняет проблему. CTRL+F5
не решает эту проблему с кешем, похоже, он не работает для такого вызова скрипта (по крайней мере, не в той версии Firefox, с которой я его тестировал).
Почему именно это происходит?
Как я могу предотвратить это?
3 ответа
Сценарий кэшируется, и браузер не извлекает новую версию с сервера.
Нам нужно отредактировать заголовок запросов на файлы в /workers
папку, используя следующий код на стороне сервера (я завернул его в пакет с api.use('webapp')
):
WebApp.rawConnectHandlers.use('/workers', function(req, res, next) {
res.setHeader('cache-control', 'must-revalidate');
next();
});
С помощью WebApp.connectHandlers
не работал, обратный вызов никогда не вызывался, поэтому я использовал rawConnectHandlers
вместо.
Я не уверен на 100%, что это лучший путь, но он работает.
Вы должны изменить заголовок ответа для файла. Возможно, это поможет вам: Явные HTTP-заголовки ответа для файлов в общедоступном каталоге Meteor.
Я не знаю точно, почему, но браузеры (по крайней мере, Chrome), по-видимому, обрабатывают рабочие сценарии иначе, чем другие файлы Javascript, в отношении кэширования при обновлении страницы, даже если заголовки, отправленные с сервера, совпадают. При обновлении страницы браузер проверяет наличие новых сценариев, на которые есть ссылки в тегах сценариев, но не тех, которые используются в качестве рабочего.
Я исправил это так, что во время сборки я включаю номер версии / время сборки / md5 содержимого файла в имя файла, так что в итоге получится что-то вроде worker.12333.js
, Преимущество этого состоит в том, что если каждое имя файла ссылается на файл, который по существу неизменен, вы можете установить заголовки с истекшим сроком давности в будущем... Таким образом, вместо того, чтобы указывать браузеру никогда не кэшировать рабочий скрипт, он может кэшировать его навсегда. https://github.com/felthy/grunt-cachebuster - один из таких инструментов, который делает это для Javascript, включенного через теги сценария, но, вероятно, есть и другие.
Проблема с этим заключается в том, что должен быть какой-то механизм, чтобы сообщить Javascript обновленное имя файла, чтобы он знал, для вызова new Worker('worker.12333.js');
, Я не уверен, что существующие доступные инструменты справятся с этим, но я просто использую время сборки проекта в секундах в качестве уникального ключа для всех файлов.
<html build-time="12333">
...
а затем получить к нему доступ через Javascript, чтобы он мог определить имя файла последнего рабочего скрипта. Это не идеально, но это довольно просто. Вы можете, вероятно, придумать другие механизмы в зависимости от ваших требований.